在 Azure Active Directory B2C 中请求访问令牌

访问令牌包含的声明可在 Azure Active Directory B2C (Azure AD B2C) 中用于识别已授予的对 API 的权限。 若要调用资源服务器,HTTP 请求必须包含访问令牌。 访问令牌在 Azure AD B2C 的响应中以 access_token 表示。

本文介绍如何请求 Web 应用程序和 Web API 的访问令牌。 有关 Azure AD B2C 中令牌的详细信息,请参阅 Azure Active Directory B2C 中的令牌概述

注意

Azure AD B2C 不支持 Web API 链(代理) - 许多体系结构都包括一个需要调用另一个下游 Web API 的 Web API,这两者均受 Azure AD B2C 保护。 此方案常见于包含 Web API 后端的客户端,该后端反过来会调用另一服务。 可以使用 OAuth 2.0 JWT 持有者凭据授权(也称为代理流)来支持这种链接的 Web API 方案。 但是,Azure AD B2C 中目前尚未实现代理流。 尽管代理适用于在 Microsoft Entra ID 中注册的应用程序,但它不适用于在 Azure AD B2C 中注册的应用程序,无论颁发令牌的租户(Microsoft Entra ID 或 Azure AD B2C)如何。

先决条件

作用域

可以通过作用域管理对受保护资源的权限。 在请求访问令牌时,客户端应用程序需要在请求的 scope 参数中指定所需的权限。 例如,对于其“应用 ID URI”为 https://contoso.partner.onmschina.cn/api 的 API,若将“作用域值”指定为 read,则作用域为 https://contoso.partner.onmschina.cn/api/read

Web API 使用作用域实施基于作用域的访问控制。 例如,可以让 Web API 用户拥有读取和写入访问权限,或者只拥有读取访问权限。 若要在同一请求中获取多个权限,可在请求的单个 scope 参数中添加多个条目并用空格分隔。

以下示例显示了在 URL 中解码的作用域:

scope=https://contoso.partner.onmschina.cn/api/read openid offline_access

以下示例显示了在 URL 中编码的作用域:

scope=https%3A%2F%2Fcontoso.partner.onmschina.cn%2Fapi%2Fread%20openid%20offline_access

如果请求的作用域数超过为客户端应用程序授予的数目,则只有在授予至少一个权限的情况下,调用才会成功。 生成的访问令牌的 scp 声明中只会填充已成功授予的权限。

OpenID Connect 范围

OpenID Connect 标准指定了多个特殊的作用域值。 以下作用域表示访问用户配置文件的权限:

  • openid - 请求 ID 令牌。
  • offline_access - 使用授权代码流请求刷新令牌。
  • 00000000-0000-0000-0000-000000000000 - 使用客户端 ID 作为范围即表示应用需要可以针对你自己的服务或 Web API(由同一客户端 ID 表示)使用的访问令牌。

如果 /authorize 请求中的 response_type 参数包含 token,那么 scope 参数必须包含至少一个将被授予的资源作用域(除 openidoffline_access 以外)。 否则,/authorize 请求会失败。

请求令牌

若要请求访问令牌,需要一个授权代码。 下面是对 /authorize 终结点发出的授权代码请求的示例:

GET https://<tenant-name>.b2clogin.cn/<tenant-name>.partner.onmschina.cn/<policy-name>/oauth2/v2.0/authorize?
client_id=<application-ID>
&nonce=anyRandomValue
&redirect_uri=https://jwt.ms
&scope=<application-ID-URI>/<scope-name>
&response_type=code

替换查询字符串中的值,如下所示:

  • <tenant-name> - Azure AD B2C 租户的名称。 如果使用自定义域,请将 tenant-name.b2clogin.cn 替换为你的域,例如 contoso.com
  • <policy-name> - 自定义策略或用户流的名称。
  • <application-ID> - 注册用于支持用户流的 Web 应用程序的应用程序标识符。
  • <application-ID-URI> - 在客户端应用程序的“公开 API”边栏选项卡下设置的应用程序标识符 URI。
  • <scope-name> - 在客户端应用程序的“公开 API”边栏选项卡下添加的范围的名称。
  • <redirect-uri> - 注册客户端应用程序时输入的重定向 URI。

若要大致了解请求的工作方式,请将该请求粘贴到浏览器中并运行它。

这是该流中你可以执行操作的交互部分。 系统会要求你完成用户流的工作流。 这可能涉及在登录表单中输入用户名和密码或其他任何数量的步骤。 完成的步骤取决于如何定义用户流。

包含授权代码的响应应类似于以下示例:

https://jwt.ms/?code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMC...

成功收到授权码后,可以使用它来请求访问令牌。 参数在 HTTP POST 请求的正文中:

POST <tenant-name>.b2clogin.cn/<tenant-name>.partner.onmschina.cn/<policy-name>/oauth2/v2.0/token HTTP/1.1
Host: <tenant-name>.b2clogin.cn
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=<application-ID>
&scope=<application-ID-URI>/<scope-name>
&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMC...
&redirect_uri=https://jwt.ms
&client_secret=2hMG2-_:y12n10vwH...

如果要测试此 POST HTTP 请求,可以使用任何 HTTP 客户端,例如 Microsoft PowerShell

成功令牌响应如下所示:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrN...",
    "token_type": "Bearer",
    "not_before": 1549647431,
    "expires_in": 3600,
    "expires_on": 1549651031,
    "resource": "f2a76e08-93f2-4350-833c-965c02483b11",
    "profile_info": "eyJ2ZXIiOiIxLjAiLCJ0aWQiOiJjNjRhNGY3ZC0zMDkxLTRjNzMtYTcyMi1hM2YwNjk0Z..."
}

使用 https://jwt.ms 检查返回的访问令牌时,看到的内容应该类似于以下示例:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dl..."
}.{
  "iss": "https://contoso0926tenant.b2clogin.cn/c64a4f7d-3091-4c73-a7.../v2.0/",
  "exp": 1549651031,
  "nbf": 1549647431,
  "aud": "f2a76e08-93f2-4350-833c-965...",
  "oid": "1558f87f-452b-4757-bcd1-883...",
  "sub": "1558f87f-452b-4757-bcd1-883...",
  "name": "David",
  "tfp": "B2C_1_signupsignin1",
  "nonce": "anyRandomValue",
  "scp": "read",
  "azp": "38307aee-303c-4fff-8087-d8d2...",
  "ver": "1.0",
  "iat": 1549647431
}.[Signature]

后续步骤