【问题标题】:Graph authentication using validated JWT使用经过验证的 JWT 进行图形身份验证
【发布时间】:2017-12-08 07:22:25
【问题描述】:

我们在 Azure 订阅中有一个应用注册,需要访问 Graph,在“所需权限”部分下设置。

Delegated Permissions image

我们的 Angular 应用程序正在启动针对 AAD 的身份验证,接收 JWT,将其附加到 Header 中的所有请求中,并将其发送到我们的 WebApi,在那里它正在被成功验证......太棒了!

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjlGWERw...

现在,我还想从 WebApi 向 Graph 发出请求,考虑到我拥有经过验证的令牌,我将通过 Authorization 标头将其传递给 Graph REST API。

request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);

但是,我得到了 401(未经授权)结果。为什么?显然我遗漏了一块拼图,但我不知道是什么。

我假设通过在 Azure 应用注册中设置 Graph 权限,当它向我们的 Angular 应用发送令牌时,它对 AAD 和 Graph 都有效......但似乎情况并非如此。

我的 JWT 如下所示。请注意,“aud”仅显示我的应用注册 ID,而不显示 Graph(如果这是问题所在,我该如何解决?)

{
  "aud": "<application id here>",
  "iss": "https://sts.windows.net/<tenant id here>/",
  "iat": 1499121655,
  "nbf": 1499121655,
  "exp": 1499125555,
  "aio": "ASQA2/8DAAAACuKzzzni2uaVoaIb9yJa4j3XuG0O+9cQQQlnqXl8Sr0=",
  "amr": [
    "pwd",
    "mfa"
  ],
  "family_name": "Smith",
  "given_name": "John",
  "name": "John Smith",
  "nonce": "<nonce here>",
  "platf": "3",
  "pwd_exp": "941678",
  "sub": "<sub here>",
  "tid": "<tenant id here>",
  "unique_name": "jsmith@smithy.com",
  "upn": "jsmith@smithy.com",
  "ver": "1.0"
}

编辑

我现在已经实现了如南宇描述的代表代码,但我仍然收到 401。前端令牌正在 WebAPI 中进行验证,然后创建对 Graph 的请求。

string authString = ConfigurationManager.AppSettings["ida:Authority"];
string clientId = ConfigurationManager.AppSettings["ida:Audience"];
string clientSecret = ConfigurationManager.AppSettings["ida:AppSecret"];
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
string graphResourceId = ConfigurationManager.AppSettings["ida:GraphResourceId"];

AuthenticationContext authenticationContext = new AuthenticationContext(authString);
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
string userAccessToken = bootstrapContext.Token;
UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);

string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;

AuthenticationResult result = await authenticationContext.AcquireTokenAsync(graphResourceId, clientCred, userAssertion);

这可以正常工作,因为返回的令牌现在具有登录用户的图表“aud”和“scp”:

"aud": "https://graph.windows.net",
"scp": "User.Read User.ReadBasic.All",
"unique_name": "jsmith@smithy.com",
"upn": "jsmith@smithy.com",

为什么我在尝试调用 /me Graph API 时仍然未经授权?

【问题讨论】:

    标签: c# asp.net azure azure-active-directory microsoft-graph-api


    【解决方案1】:

    如果要调用 microsoft graph api ,则需要获取 microsoft graph api 的 access token ,也就是说 access token 声明中的 aud(audience) 应该是 https://graph.microsoft.com

    在您的场景中,如果用户登录客户端应用程序,则客户端应用程序调用您的 web api,在 web api 中,您想调用 microsoft graph api,有两种方法可以实现:

    1.使用 OAuth 2.0 On-Behalf-Of 流来委派用户的身份并向第二层 Web API 进行身份验证。见代码示例here

    2.使用 OAuth 2.0 Client Credentials Grant ,Azure AD 对 Web api 应用程序进行身份验证并返回用于调用 Microsoft graph 的 JWT 访问令牌。在这种情况下,您应该在 web api 应用程序中授予 microsft 图的权限。参见代码示例here

    以上场景详情请点击here

    【讨论】:

    • 非常感谢您的帮助。这确实让我感动,但我仍然得到 401。请参阅上面的编辑。
    • 所呈现的 2 个选项的一个重要区别。前者是用户身份验证,它将授予您代表用户访问资源的范围。这适用于实际的代表流程,但也适用于身份验证代码和隐式流程。后一个选项(客户端凭据)是应用程序身份验证。在这种情况下,Azure AD 会向您的应用授予一个令牌,该令牌具有您的应用本身可以访问的角色,但不会授予您用户可能拥有的特定访问权限,仅授予应用。 @GT-DownUnder 仅供参考。
    • 有关更多信息,请查看this 文档并搜索标题:“配置客户端应用程序以调用 Web API”。
    • @GT-DownUnder,你用的是哪个api?您的访问令牌适用于 azure ad graph api (graph.windows.net) ,而不适用于 microsoft graph api (graph.microsoft.com) ,因此您需要使用 azure ad graph api operations 。或者,如果您想调用 microsoft graph api,则需要获取资源令牌(graph.microsoft.com
    • @NanYu-MSFT,你真是个天才!太感谢了!问题在于 API。虽然我在 apps.dev 中设置了应用程序以使用 Graph,但我设置了 AAD Graph API,而不是 Microsoft Graph API。再次,非常感谢。
    猜你喜欢
    • 2016-04-07
    • 1970-01-01
    • 2023-03-27
    • 2021-05-29
    • 2017-07-30
    • 2018-06-30
    • 2018-08-03
    • 2021-02-06
    • 2022-12-03
    相关资源
    最近更新 更多