You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure B2C刷新令牌不包含自定义声明问题排查

问题原因与解决办法

问题根源

首次登录时,REST API返回的自定义声明只是临时加入到Access Token中,但没有被持久化到Azure AD B2C的用户存储里。刷新令牌时,B2C不会重新触发登录阶段的REST API验证流程,只会从已存储的用户数据中读取声明生成新令牌,未持久化的声明自然不会出现在刷新后的令牌中。

解决步骤

1. 配置自定义声明持久化存储

在自定义策略中,先在<ClaimsSchema>里声明这些自定义字段,再在<RelyingParty>的<PersistedClaims>中添加配置,让B2C将这些值存入用户档案:

<ClaimsSchema>
  <ClaimType Id="personId">
    <DisplayName>Person ID</DisplayName>
    <DataType>string</DataType>
  </ClaimType>
  <ClaimType Id="comUsername">
    <DisplayName>Company Username</DisplayName>
    <DataType>string</DataType>
  </ClaimType>
  <ClaimType Id="wcfToken">
    <DisplayName>WCF Token</DisplayName>
    <DataType>string</DataType>
  </ClaimType>
  <ClaimType Id="organizationCode">
    <DisplayName>Organization Code</DisplayName>
    <DataType>string</DataType>
  </ClaimType>
</ClaimsSchema>

<RelyingParty>
  <DefaultUserJourney ReferenceId="SignUpOrSignIn" />
  <TechnicalProfile Id="PolicyProfile">
    <DisplayName>PolicyProfile</DisplayName>
    <Protocol Name="OpenIdConnect" />
    <OutputClaims>
      <!-- 保留原有输出声明,添加自定义声明 -->
      <OutputClaim ClaimTypeReferenceId="personId" />
      <OutputClaim ClaimTypeReferenceId="comUsername" />
      <OutputClaim ClaimTypeReferenceId="wcfToken" />
      <OutputClaim ClaimTypeReferenceId="organizationCode" />
    </OutputClaims>
    <PersistedClaims>
      <!-- 指定要持久化的自定义声明 -->
      <PersistedClaim ClaimTypeReferenceId="personId" />
      <PersistedClaim ClaimTypeReferenceId="comUsername" />
      <PersistedClaim ClaimTypeReferenceId="wcfToken" />
      <PersistedClaim ClaimTypeReferenceId="organizationCode" />
    </PersistedClaims>
    <SubjectNamingInfo ClaimType="sub" />
  </TechnicalProfile>
</RelyingParty>

2. 配置刷新令牌时读取持久化声明

找到策略中的JwtIssuer技术配置文件,添加输入和输出声明,确保刷新令牌时B2C将存储的声明写入新的Access Token:

<TechnicalProfile Id="JwtIssuer">
  <DisplayName>JWT Issuer</DisplayName>
  <Protocol Name="None" />
  <OutputTokenFormat>JWT</OutputTokenFormat>
  <Metadata>
    <!-- 保留原有元数据配置 -->
  </Metadata>
  <InputClaims>
    <!-- 从用户存储读取自定义声明 -->
    <InputClaim ClaimTypeReferenceId="personId" />
    <InputClaim ClaimTypeReferenceId="comUsername" />
    <InputClaim ClaimTypeReferenceId="wcfToken" />
    <InputClaim ClaimTypeReferenceId="organizationCode" />
  </InputClaims>
  <OutputClaims>
    <!-- 将自定义声明输出到新令牌 -->
    <OutputClaim ClaimTypeReferenceId="personId" />
    <OutputClaim ClaimTypeReferenceId="comUsername" />
    <OutputClaim ClaimTypeReferenceId="wcfToken" />
    <OutputClaim ClaimTypeReferenceId="organizationCode" />
  </OutputClaims>
  <CryptographicKeys>
    <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
  </CryptographicKeys>
</TechnicalProfile>

3. (可选)刷新时重新获取动态声明

如果像wcfToken这类声明有有效期,需要每次刷新都重新调用API获取,可以在用户旅程中添加针对刷新场景的步骤,用<Preconditions>判断是否为刷新流程,再触发对应的REST API调用:

<UserJourney Id="SignUpOrSignIn">
  <OrchestrationSteps>
    <!-- 保留原有登录流程步骤 -->
    <!-- 仅在刷新令牌时执行的REST调用步骤 -->
    <OrchestrationStep Order="10" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>isRefreshToken</Value>
          <Value>true</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="RESTAPI-Refresh" TechnicalProfileReferenceId="RESTAPI-RefreshClaims" />
      </ClaimsExchanges>
    </OrchestrationStep>
  </OrchestrationSteps>
</UserJourney>

4. 代码端检查

刷新令牌时,确保scopes参数包含对应资源的范围(如果自定义声明与特定范围绑定),一般默认的openid等基础范围即可返回持久化声明。

内容的提问来源于stack exchange,提问作者Arjun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:31:12