在Azure AD B2C自定义策略中添加JSON类型声明报错的解决方法
解决Azure AD B2C映射Salesforce嵌套JSON声明时的JObject类型错误
已通过OpenIdConnect协议将Salesforce作为身份提供商(IdP)接入Azure AD B2C且运行正常。Salesforce返回的令牌中包含一个嵌套JSON结构的声明:
"custom_attributes": { "UserRoleName": "SC Management" }
尝试将custom_attributes作为Claim添加到B2C自定义策略时,出现错误:
"An unexpected type "Newtonsoft.Json.Linq.JObject" was encountered of the claim with claim type id "custom_attributes"."
错误原因
Azure AD B2C的ClaimType若定义为string,无法直接接收嵌套的JSON对象(JObject类型)。直接映射整个custom_attributes会导致类型不匹配——B2C期望字符串,但收到的是JSON对象。
解决方案
提供两种可行方案,推荐第一种直接提取嵌套属性的方式,更贴合业务实际需求;第二种适用于需要保留完整JSON结构的场景。
方案一:直接提取嵌套属性(推荐)
无需映射整个custom_attributes对象,直接提取其中的具体属性(如UserRoleName):
- 在TrustFrameworkBase.xml中添加目标属性的ClaimType
<BuildingBlocks> <ClaimsSchema> <ClaimType Id="UserRoleName"> <DisplayName>User Role Name</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OpenIdConnect" PartnerClaimType="custom_attributes.UserRoleName" /> </DefaultPartnerClaimTypes> </ClaimType> ... </ClaimsSchema> ... </BuildingBlocks>
- 在TrustFrameworkExtensions.xml的Salesforce TechnicalProfile中配置输出Claim
<ClaimsProviders> <ClaimsProvider> <Domain>salesforce.com</Domain> <DisplayName>Salesforce</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="Salesforce-OpenIdConnect"> <OutputClaims> <OutputClaim ClaimTypeReferenceId="UserRoleName" PartnerClaimType="custom_attributes.UserRoleName" /> ... </OutputClaims> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> </ClaimsProviders>
- 在SignUpOrSignin.xml的RelyingParty中输出该Claim
<RelyingParty> <TechnicalProfile Id="PolicyProfile"> <DisplayName>PolicyProfile</DisplayName> <Protocol Name="OpenIdConnect" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="UserRoleName" PartnerClaimType="user_role_name" /> <!-- 可自定义为应用期望的字段名 --> ... </OutputClaims> </TechnicalProfile> </RelyingParty>
方案二:将嵌套JSON对象序列化为字符串
若需保留custom_attributes的完整JSON结构,可通过ClaimsTransformation将JObject转换为字符串:
- 在TrustFrameworkBase.xml中添加ClaimType和转换规则
<BuildingBlocks> <ClaimsSchema> <!-- 临时Claim用于接收原始JObject --> <ClaimType Id="custom_attributes_raw"> <DisplayName>Raw Custom Attributes</DisplayName> <DataType>object</DataType> </ClaimType> <!-- 最终输出的字符串类型Claim --> <ClaimType Id="custom_attributes"> <DisplayName>Custom Attributes</DisplayName> <DataType>string</DataType> </ClaimType> ... </ClaimsSchema> <ClaimsTransformations> <!-- 将JObject转换为JSON字符串 --> <ClaimsTransformation Id="ConvertCustomAttributesToString" TransformationMethod="ConvertJsonToString"> <InputClaims> <InputClaim ClaimTypeReferenceId="custom_attributes_raw" TransformationClaimType="inputJson" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="custom_attributes" TransformationClaimType="outputJson" /> </OutputClaims> </ClaimsTransformation> </ClaimsTransformations> ... </BuildingBlocks>
- 在TrustFrameworkExtensions.xml的Salesforce TechnicalProfile中配置转换流程
<ClaimsProviders> <ClaimsProvider> <Domain>salesforce.com</Domain> <DisplayName>Salesforce</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="Salesforce-OpenIdConnect"> <OutputClaims> <!-- 先接收原始JObject --> <OutputClaim ClaimTypeReferenceId="custom_attributes_raw" PartnerClaimType="custom_attributes" /> ... </OutputClaims> <!-- 执行JSON转字符串的转换 --> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="ConvertCustomAttributesToString" /> </OutputClaimsTransformations> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> </ClaimsProviders>
- 在SignUpOrSignin.xml的RelyingParty中输出字符串类型的Claim
<RelyingParty> <TechnicalProfile Id="PolicyProfile"> <DisplayName>PolicyProfile</DisplayName> <Protocol Name="OpenIdConnect" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="custom_attributes" PartnerClaimType="custom_attributes" /> ... </OutputClaims> </TechnicalProfile> </RelyingParty>
内容的提问来源于stack exchange,提问作者KlausZ
相关产品推荐
相关产品推荐

