Azure AD B2C自定义策略UserInfo端点:移除原声明保留重命名声明
Azure AD B2C自定义策略UserInfo端点声明重命名问题
背景
我正在使用Azure AD B2C自定义策略实现UserInfo端点,已完成UserInfo端点、TechnicalProfile和UserJourney的配置,同时搭建了RESTful ClaimsProvider从数据库获取声明数据。目前UserInfo端点的UserJourney运行正常,RESTful API调用也能正常执行。
问题描述
我需要在UserInfo响应返回前重命名部分声明。在"Token Issuer" ClaimsProvider的TechnicalProfile中,我为signInNames.emailAddress声明添加了PartnerClaimType属性,将其重命名为email:
<!-- 以下声明会在存在于Claims Bag时返回给UserInfo端点 --> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId"/> <InputClaim ClaimTypeReferenceId="givenName"/> <InputClaim ClaimTypeReferenceId="surname"/> <InputClaim ClaimTypeReferenceId="displayName"/> <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/> </InputClaims>
但响应中同时出现了email和signInNames.emailAddress两个字段,我需要移除signInNames.emailAddress:
{ "objectId": "fd604948-f5a3-4046-ad08-5c7814839ad0", "givenName": "Alice", "surname": "Allgood", "displayName": "Alice Allgood", "email": "******@mydomain.xyz", "signInNames.emailAddress": "******@mydomain.xyz" }
核心问题:如何阻止signInNames.emailAddress出现在UserInfo响应中?
完整配置代码
UserInfo端点的ClaimsProvider
<ClaimsProvider> <!-- UserInfo端点的Claims Provider --> <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> <!-- 以下声明会在存在于Claims Bag时返回给UserInfo端点 --> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId"/> <InputClaim ClaimTypeReferenceId="givenName"/> <InputClaim ClaimTypeReferenceId="surname"/> <InputClaim ClaimTypeReferenceId="displayName"/> <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/> </InputClaims> </TechnicalProfile> <TechnicalProfile Id="UserInfoAuthorization"> <DisplayName>UserInfo授权</DisplayName> <Protocol Name="None"/> <InputTokenFormat>JWT</InputTokenFormat> <Metadata> <!-- 更新下方的Issuer和Audience --> <!-- Audience可选,Issuer必填 --> <Item Key="issuer">https://mydomain.b2clogin.com/eb3cdb18-ca7c-4557-8c01-92b5a13725e8/v2.0/</Item> <Item Key="audience">[ "1abc4fa4-9aed-4697-af1b-d6310d098a6e" ]</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"/> </OutputClaims> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider>
UserInfo端点的UserJourney
<!-- UserInfo端点 --> <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="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="GetUserInfoClaims" TechnicalProfileReferenceId="UserInfoClaimsViaHttp"/> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="UserInfoIssuer"/> </OrchestrationSteps> </UserJourney>
包含UserInfo端点配置的RelyingParty
<RelyingParty> <DefaultUserJourney ReferenceId="SignIn"/> <Endpoints> <!-- UserInfo端点 --> <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="signInName" PartnerClaimType="email"/> <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/> <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}"/> </OutputClaims> <SubjectNamingInfo ClaimType="sub"/> </TechnicalProfile> </RelyingParty>
解决方案
方法1:使用声明转换移除原声明
- 先定义一个
RemoveClaim类型的声明转换:
<ClaimsTransformations> <ClaimsTransformation Id="RemoveSignInNamesEmail" TransformationMethod="RemoveClaim"> <InputClaims> <InputClaim ClaimTypeReferenceId="signInNames.emailAddress"/> </InputClaims> </ClaimsTransformation> </ClaimsTransformations>
- 在
UserInfoIssuerTechnicalProfile中添加该转换,放在InputClaims之后:
<TechnicalProfile Id="UserInfoIssuer"> <!-- 保留原有配置 --> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId"/> <InputClaim ClaimTypeReferenceId="givenName"/> <InputClaim ClaimTypeReferenceId="surname"/> <InputClaim ClaimTypeReferenceId="displayName"/> <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/> </InputClaims> <!-- 添加声明转换 --> <InputClaimsTransformations> <InputClaimsTransformation ReferenceId="RemoveSignInNamesEmail"/> </InputClaimsTransformations> </TechnicalProfile>
方法2:明确控制输出声明(推荐)
将UserInfoIssuer中的InputClaims替换为OutputClaims,仅列出需要返回的声明,未列出的声明不会出现在响应中:
<TechnicalProfile Id="UserInfoIssuer"> <DisplayName>JSON Issuer</DisplayName> <Protocol Name="None"/> <OutputTokenFormat>JSON</OutputTokenFormat> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer"/> </CryptographicKeys> <!-- 替换InputClaims为OutputClaims --> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId"/> <OutputClaim ClaimTypeReferenceId="givenName"/> <OutputClaim ClaimTypeReferenceId="surname"/> <OutputClaim ClaimTypeReferenceId="displayName"/> <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email"/> <!-- 其他需要返回的声明请在此处添加 --> </OutputClaims> </TechnicalProfile>
这种方式下,只有OutputClaims中定义的声明会被返回,原signInNames.emailAddress会被映射为email,不会单独出现在响应里。
内容的提问来源于stack exchange,提问作者realmikep
相关产品推荐
相关产品推荐

