Azure AD B2C:能否在TechnicalProfile的Metadata Item中使用声明值?
问题与解决方案
问题场景
现有如下B2C自定义策略中的TechnicalProfile:
<TechnicalProfile Id="ExternalDirectorySignInProfile"> <DisplayName>Multi-Tenant AAD</DisplayName> <Protocol Name="OpenIdConnect" /> <Metadata> <Item Key="METADATA">https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration</Item> <!-- enable sign in from specific token issuers (v2.0) --> <Item Key="ValidTokenIssuerPrefixes">{Claim:tokenIssuerPrefix}</Item> ... blah ... </Metadata> ... blah ... </TechnicalProfile>
尝试在ValidTokenIssuerPrefixes元数据中使用声明解析器{Claim:tokenIssuerPrefix}时,出现报错:
The ValidTokenIssuerPrefixes metadata item in technical profile 'ExternalDirectorySignInProfile' of policy 'B2C_1A_TrustFrameworkExtensions_Debug' does not contain a list of comma delimited URIs
此前已通过编排步骤调用REST服务获取到tokenIssuerPrefix声明,目标是仅允许该声明对应的AAD租户完成认证,而非开放给所有多租户AAD用户。官方文档明确声明解析器仅在输入/输出声明中生效,无法直接用于元数据配置。
替代实现方案
既然无法在元数据中动态注入声明值,可改为在用户完成OIDC认证后,验证返回的iss(token issuer)声明是否匹配tokenIssuerPrefix,具体步骤如下:
1. 配置OIDC TechnicalProfile获取iss声明
在ExternalDirectorySignInProfile的<OutputClaims>节点中添加对iss声明的获取:
<OutputClaims> <!-- 原有输出声明保留 --> <OutputClaim ClaimTypeReferenceId="iss" PartnerClaimType="iss" /> </OutputClaims>
2. 添加验证用的TechnicalProfile
定义专用于验证issuer的TechnicalProfile,调用ClaimsTransformation完成匹配检查:
<TechnicalProfile Id="ValidateTokenIssuer"> <DisplayName>Validate Token Issuer</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <InputClaims> <InputClaim ClaimTypeReferenceId="iss" /> <InputClaim ClaimTypeReferenceId="tokenIssuerPrefix" /> </InputClaims> <ClaimsTransformations> <ClaimsTransformation ReferenceId="CheckIssuerStartsWithPrefix" /> <ClaimsTransformation ReferenceId="AssertIssuerIsValid" /> </ClaimsTransformations> <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /> </TechnicalProfile>
3. 编写ClaimsTransformation规则
规则1:检查iss是否以指定前缀开头
<ClaimsTransformation Id="CheckIssuerStartsWithPrefix" TransformationMethod="StringStartsWith"> <InputClaims> <InputClaim ClaimTypeReferenceId="iss" TransformationClaimType="inputClaim" /> <InputClaim ClaimTypeReferenceId="tokenIssuerPrefix" TransformationClaimType="prefix" /> </InputClaims> <InputParameters> <InputParameter Id="ignoreCase" DataType="boolean" Value="true" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="issuerValidated" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation>
规则2:断言验证结果为真,否则抛出错误
<ClaimsTransformation Id="AssertIssuerIsValid" TransformationMethod="AssertBooleanClaimIsEqualToValue"> <InputClaims> <InputClaim ClaimTypeReferenceId="issuerValidated" TransformationClaimType="inputClaim" /> </InputClaims> <InputParameters> <InputParameter Id="valueToCompareTo" DataType="boolean" Value="true" /> <InputParameter Id="errorMessage" DataType="string" Value="Invalid tenant. Only pre-approved tenants can sign in." /> </InputParameters> </ClaimsTransformation>
4. 声明必要的ClaimType
在<ClaimsSchema>中添加所需的声明类型定义:
<ClaimType Id="iss"> <DisplayName>Token Issuer</DisplayName> <DataType>string</DataType> </ClaimType> <ClaimType Id="issuerValidated"> <DisplayName>Issuer Validation Result</DisplayName> <DataType>boolean</DataType> </ClaimType>
5. 关联验证步骤到原TechnicalProfile
在ExternalDirectorySignInProfile中添加验证引用,确保认证完成后自动执行issuer检查:
<ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="ValidateTokenIssuer" /> </ValidationTechnicalProfiles>
原理说明
该方案绕开元数据无法动态赋值的限制,通过OIDC协议获取token的issuer值,再利用ClaimsTransformation的字符串匹配和断言功能,强制验证issuer是否符合预定义的前缀,不符合则直接阻断登录流程,实现仅允许指定租户用户认证的目标。
内容的提问来源于stack exchange,提问作者Alasdair C-S
相关产品推荐
相关产品推荐

