UserInfo 终结点

开始之前,请使用此页顶部的“选择策略类型”选择器来选择要设置的策略类型。 Azure Active Directory B2C 提供了两种定义用户如何与应用程序交互的方法:通过预定义的用户流,或者通过可完全配置的自定义策略。 对于每种方法,本文中所需的步骤都不同。

UserInfo 终结点是 OpenID Connect 标准 (OIDC) 规范的一部分,用于返回有关已通过身份验证的用户的声明。 使用 EndPoint 元素在信赖方策略中定义 UserInfo 终结点。

此功能仅适用于自定义策略。 对于设置步骤,请在前面的选择器中选择“自定义策略”。

先决条件

UserInfo 终结点概述

用户信息 UserJourney 指定:

  • 授权:使用持有者令牌保护 UserInfo 终结点。 颁发的访问令牌显示在 UserInfo 终结点的 Authorization 标头中。 策略指定用于验证传入令牌并提取声明(例如用户的 objectId)的技术配置文件。 用户的 objectId 用于检索在 UserInfo 终结点旅程的响应中返回的声明。
  • 业务流程步骤
    • 业务流程步骤用于收集有关用户的信息。 用户旅程会根据传入访问令牌中的声明,调用 Microsoft Entra ID 技术配置文件来检索有关用户的数据,例如按 objectId 读取用户。
    • 可选的业务流程步骤 - 可以添加更多的业务流程步骤(例如 REST API 技术配置文件)来检索有关用户的详细信息。
    • UserInfo 颁发者 - 指定 UserInfo 终结点返回的声明列表。

创建 UserInfo 终结点

1.添加 Token Issuer 技术配置文件

  1. 打开 TrustFrameworkExtensions.xml 文件。

  2. 如果尚不存在该文件,则添加 ClaimsProvider 元素及其子元素作为 BuildingBlocks 元素下的第一个元素。

  3. 添加以下声明提供程序:

    <!-- 
    <ClaimsProviders> -->
      <ClaimsProvider>
        <DisplayName>Token Issuer</DisplayName>
        <TechnicalProfiles>
          <TechnicalProfile Id="UserInfoIssuer">
            <DisplayName>JSON Issuer</DisplayName>
            <Protocol Name="None" />
            <OutputTokenFormat>JSON</OutputTokenFormat>
            <CryptographicKeys>
              <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
            </CryptographicKeys>
            <!-- The Below claims are what will be returned on the UserInfo Endpoint if in the Claims Bag-->
            <InputClaims>
              <InputClaim ClaimTypeReferenceId="objectId"/>
              <InputClaim ClaimTypeReferenceId="givenName"/>
              <InputClaim ClaimTypeReferenceId="surname"/>
              <InputClaim ClaimTypeReferenceId="displayName"/>
              <InputClaim ClaimTypeReferenceId="signInNames.emailAddress"/>
            </InputClaims>
          </TechnicalProfile>
          <TechnicalProfile Id="UserInfoAuthorization">
            <DisplayName>UserInfo authorization</DisplayName>
            <Protocol Name="None" />
            <InputTokenFormat>JWT</InputTokenFormat>
            <Metadata>
              <!-- Update the Issuer and Audience below -->
              <!-- Audience is optional, Issuer is required-->
              <Item Key="issuer">https://yourtenant.b2clogin.cn/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/</Item>
              <Item Key="audience">[ "00001111-aaaa-2222-bbbb-3333cccc4444", "11112222-bbbb-3333-cccc-4444dddd5555" ]</Item>
              <Item Key="client_assertion_type">urn:ietf:params:oauth:client-assertion-type:jwt-bearer</Item>
            </Metadata>
            <CryptographicKeys>
              <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
            </CryptographicKeys>
            <OutputClaims>
              <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
              <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/>
              <!-- Optional claims to read from the access token. -->
              <!-- <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name"/>
                 <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="family_name"/>
                 <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name"/> -->
            </OutputClaims>
          </TechnicalProfile>
        </TechnicalProfiles>
      </ClaimsProvider>
    <!-- 
    </ClaimsProviders> -->
    
  4. UserInfoIssuer 技术配置文件中的 InputClaims 节指定要返回的属性。 在用户旅程结束时,会调用 UserInfoIssuer 技术配置文件。

  5. UserInfoAuthorization 技术配置文件会验证签名、颁发者名称和令牌受众,并从入站令牌中提取声明。 请更改以下元数据,使之反映你的环境:

    1. issuer - 此值必须与访问令牌声明中的 iss 声明相同。 Azure AD B2C 颁发的令牌使用 https://yourtenant.b2clogin.cn/your-tenant-id/v2.0/ 格式的颁发者。 详细了解令牌自定义

    2. IdTokenAudience - 必须与访问令牌声明中的 aud 声明相同。 在 Azure AD B2C 中,aud 声明是信赖方应用程序的 ID。 此值为集合,支持多个使用逗号分隔符的值。

      在以下访问令牌中,iss 声明值为 https://contoso.b2clogin.cn/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/aud 声明值为 00001111-aaaa-2222-bbbb-3333cccc4444

      {
        "exp": 1605549468,
        "nbf": 1605545868,
        "ver": "1.0",
        "iss": "https://contoso.b2clogin.cn/11111111-1111-1111-1111-111111111111/v2.0/",
        "sub": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
        "aud": "00001111-aaaa-2222-bbbb-3333cccc4444",
        "acr": "b2c_1a_signup_signin",
        "nonce": "defaultNonce",
        "iat": 1605545868,
        "auth_time": 1605545868,
        "name": "John Smith",
        "given_name": "John",
        "family_name": "Smith",
        "tid": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
      }
      
  6. UserInfoAuthorization 技术配置文件的 OutputClaims 元素指定要从访问令牌中读取的属性。 ClaimTypeReferenceId 是对声明类型的引用。 可选的 PartnerClaimType 是在访问令牌中定义的声明的名称。

2.添加 UserJourney 元素

UserJourney 元素定义用户与应用程序进行交互时使用的路径。 如果 UserJourneys 元素不具有标识为 UserInfoJourneyUserJourney,则添加一个:

<!-- 
<UserJourneys> -->
  <UserJourney Id="UserInfoJourney" DefaultCpimIssuerTechnicalProfileReferenceId="UserInfoIssuer">
    <Authorization>
      <AuthorizationTechnicalProfiles>
        <AuthorizationTechnicalProfile ReferenceId="UserInfoAuthorization" />
      </AuthorizationTechnicalProfiles>
    </Authorization>
    <OrchestrationSteps >
      <OrchestrationStep Order="1" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges UserIdentity="false">
          <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="2" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="UserInfoIssuer" />
    </OrchestrationSteps>
  </UserJourney>
<!-- 
</UserJourneys> -->

3.将终结点包括到信赖方策略中

若要在信赖方应用程序中包括 UserInfo 终结点,请将 Endpoint 元素添加到 SocialAndLocalAccounts/SignUpOrSignIn.xml 文件中。

<!--
<RelyingParty> -->
  <Endpoints>
    <Endpoint Id="UserInfo" UserJourneyReferenceId="UserInfoJourney" />
  </Endpoints>
<!-- 
</RelyingParty> -->

完成的信赖方元素将如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TrustFrameworkPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06" PolicySchemaVersion="0.3.0.0" TenantId="yourtenant.partner.onmschina.cn" PolicyId="B2C_1A_signup_signin" PublicPolicyUri="http://yourtenant.partner.onmschina.cn/B2C_1A_signup_signin">
  <BasePolicy>
    <TenantId>yourtenant.partner.onmschina.cn</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
  </BasePolicy>
  <RelyingParty>
    <DefaultUserJourney ReferenceId="SignUpOrSignIn" />
    <Endpoints>
      <Endpoint Id="UserInfo" UserJourneyReferenceId="UserInfoJourney" />
    </Endpoints>
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="displayName" />
        <OutputClaim ClaimTypeReferenceId="givenName" />
        <OutputClaim ClaimTypeReferenceId="surname" />
        <OutputClaim ClaimTypeReferenceId="email" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>
</TrustFrameworkPolicy>

4.上传文件

  1. 登录 Azure 门户
  2. 如果有权访问多个租户,请选择顶部菜单中的“设置”图标,切换到“目录 + 订阅”菜单中的 Azure AD B2C 租户。
  3. 选择 Azure 门户左上角的“所有服务”,然后搜索并选择“Azure AD B2C” 。
  4. 选择“标识体验框架”。
  5. 在“自定义策略”页上,选择“上传自定义策略” 。
  6. 选择“覆盖自定义策略(若已存在)”,然后搜索并选择 TrustframeworkExtensions.xml 文件。
  7. 单击“上载” 。
  8. 针对信赖方文件(例如 SignUpOrSignIn.xml)重复步骤 5 到 7。

调用 UserInfo 终结点

UserInfo 终结点使用标准 OAuth2 持有者令牌 API,该 API 通过使用在获取应用程序令牌时收到的访问令牌来调用。 它返回一个 JSON 响应,其中包含有关用户的声明的。 UserInfo 终结点在 Azure AD B2C 上托管,具体位置如下:

https://yourtenant.b2clogin.cn/yourtenant.partner.onmschina.cn/policy-name/openid/v2.0/userinfo

/.well-known 配置终结点(OpenID Connect 发现文档)会列出 userinfo_endpoint 字段。 可以使用 /.well-known 配置终结点以编程方式发现 UserInfo 终结点,具体位置如下:

https://yourtenant.b2clogin.cn/yourtenant.partner.onmschina.cn/policy-name/v2.0/.well-known/openid-configuration 

测试策略

  1. 在“自定义策略”下,选择已将 UserInfo 终结点与之集成的策略。 例如,B2C_1A_SignUpOrSignIn。
  2. 选择“立即运行”。
  3. 在“选择应用程序”下,选择你之前注册的应用程序。 对于“选择回复 URL”,请选择 https://jwt.ms。 有关详细信息,请参阅在 Azure Active Directory B2C 中注册 Web 应用程序
  4. 使用电子邮件地址或社交帐户注册或登录。
  5. https://jwt.ms 网站复制采用编码格式的 id_token。 你可以使用此方法向 UserInfo 终结点提交 GET 请求并检索用户信息。
  6. 向 UserInfo 终结点提交 GET 请求并检索用户信息。
GET /yourtenant.partner.onmschina.cn/b2c_1a_signup_signin/openid/v2.0/userinfo
Host: b2cninja.b2clogin.cn
Authorization: Bearer <your access token>

成功的响应如下所示:

{
    "objectId": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
    "givenName": "John",
    "surname": "Smith",
    "displayName": "John Smith",
    "signInNames.emailAddress": "john.s@contoso.com"
}

提供可选声明

要为应用提供更多声明,请按照以下步骤操作:

  1. 添加用户属性并自定义用户输入

  2. 信赖方策略技术配置文件 OutputClaims 元素修改为要提供的声明。 使用 DefaultValue 属性设置默认值。 也可将默认值设置为声明解析器,例如 {Context:CorrelationId}。 要强制使用默认值,请将 AlwaysUseDefaultValue 属性设置为 true。 以下示例使用默认值添加城市声明。

    <RelyingParty>
      ...
      <TechnicalProfile Id="PolicyProfile">
        ...
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="city" DefaultValue="Berlin" />
        </OutputClaims>
        ...
      </TechnicalProfile>
    </RelyingParty>
    
  3. 将 UserInfoIssuer 技术配置文件 InputClaims 元素修改为要提供的声明。 使用 PartnerClaimType 属性将声明返回的名称更改为应用。 以下示例添加了城市声明并更改了一些声明的名称。

    <TechnicalProfile Id="UserInfoIssuer">
      ...
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="objectId" />
        <InputClaim ClaimTypeReferenceId="city" />
        <InputClaim ClaimTypeReferenceId="givenName" />
        <InputClaim ClaimTypeReferenceId="surname" PartnerClaimType="familyName" />
        <InputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" />
        <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email" />
      </InputClaims>
      ...
    </TechnicalProfile>
    

后续步骤

  • 可以在 GitHub 上找到 UserInfo 终结点策略的示例。