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
相关产品推荐
相关产品推荐

