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

无法通过Azure AD B2C自定义策略将SAML IdP的Claims传递至SAML SP

Azure AD B2C自定义策略:将SAML IdP的Claims传递至SAML SP

问题描述

我正尝试通过Azure AD B2C自定义策略,将部分Claims从SAML IdP传递至SAML SP。目前可以正常登录,且能看到SAML IdP返回的相关属性,但无法将这些属性传递给SAML SP。我首先希望能传递groups Claims,同时希望避免调用MS Graph的REST接口来实现此功能,假设这些Claims已存在于Claims Bag中,希望找到简便的传递方法。

提供的自定义策略代码

登录策略(B2C_1A_SAML_TF_SP_SignIn)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TrustFrameworkPolicy
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06"
  PolicySchemaVersion="0.3.0.0"
  TenantId="myb2.onmicrosoft.com"
  PolicyId="B2C_1A_SAML_TF_SP_SignIn"
  PublicPolicyUri="http://myb2.onmicrosoft.com/B2C_1A_SAML_TF_SP_SignIn"

  TenantObjectId="f8cba1c5-22e8-4ddc-98c3-3b6afc4d5350" 
  DeploymentMode="Development" 
  UserJourneyRecorderEndpoint="urn:journeyrecorder:applicationinsights">
  
  <BasePolicy>
    <TenantId>myb2.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_SAML_TFExtensions</PolicyId>
  </BasePolicy>

  <RelyingParty>
    <DefaultUserJourney ReferenceId="X-SignIn" />
      <TechnicalProfile Id="PolicyProfile">
        <DisplayName>PolicyProfile</DisplayName>
        <Protocol Name="SAML2"/>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="objectId"/>
          <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="" />
          <OutputClaim ClaimTypeReferenceId="displayName" />
          <OutputClaim ClaimTypeReferenceId="givenName" />      
          <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="last_name"/>
          <OutputClaim ClaimTypeReferenceId="ipaddr"/>
          <OutputClaim ClaimTypeReferenceId="groups" DefaultValue="" />
          <OutputClaim ClaimTypeReferenceId="role" />
        </OutputClaims>
        <SubjectNamingInfo ClaimType="objectId" ExcludeAsClaim="false"/>
      </TechnicalProfile>
  </RelyingParty>
</TrustFrameworkPolicy>

用户旅程配置(X-SignIn)

<UserJourneys>
  <UserJourney Id="X-SignIn">
    <OrchestrationSteps>
      <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.x-signin">
        <ClaimsProviderSelections>
          <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
          <ClaimsProviderSelection TargetClaimsExchangeId="X-SignIn" />
        </ClaimsProviderSelections>
        <ClaimsExchanges>
          <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="2" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
          <ClaimsExchange Id="X-SignIn" TechnicalProfileReferenceId="X-SAML2" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="3" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>authenticationSource</Value>
            <Value>localAccountAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="4" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="5" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>authenticationSource</Value>
            <Value>socialIdpAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="6" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="7" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="Saml2AssertionIssuer"/>
    </OrchestrationSteps>
    <ClientDefinition ReferenceId="DefaultWeb" />
  </UserJourney>
</UserJourneys>

SAML追踪器信息

  • SAML IdP:已确认返回包含groups在内的目标属性
  • SAML断言发布者:当前输出的断言中未包含目标groups属性

解决方案

要将SAML IdP返回的Claims传递到SAML SP,需完成以下配置调整:

1. 确保SAML IdP技术配置文件捕获目标Claims

在B2C_1A_SAML_TFExtensions策略的X-SAML2技术配置文件中,添加groups的输出声明,映射到IdP实际返回的属性名称:

<TechnicalProfile Id="X-SAML2">
  <DisplayName>X SAML IdP</DisplayName>
  <Protocol Name="SAML2"/>
  <Metadata>
    <!-- 保留现有元数据配置 -->
  </Metadata>
  <OutputClaims>
    <!-- 保留其他已配置的Claims -->
    <OutputClaim ClaimTypeReferenceId="groups" PartnerClaimType="urn:oid:1.2.840.113556.1.4.221"/> <!-- 替换为IdP返回的groups属性名称 -->
  </OutputClaims>
  <!-- 保留其他配置 -->
</TechnicalProfile>

提示:PartnerClaimType的值需与SAML IdP返回的属性名称完全匹配,可通过SAML追踪器确认。

2. 移除RelyingParty中groups的默认值

当前PolicyProfile中groups声明的DefaultValue=""会覆盖Claims Bag中的实际值,需删除该属性:

<OutputClaim ClaimTypeReferenceId="groups" /> <!-- 移除DefaultValue属性 -->

3. 确认groups的ClaimType定义正确

在扩展策略的BuildingBlocks节点中,确保groups的ClaimType数据类型与IdP返回的格式匹配(多组用stringCollection,单组用string):

<BuildingBlocks>
  <ClaimsSchema>
    <ClaimType Id="groups">
      <DisplayName>Groups</DisplayName>
      <DataType>stringCollection</DataType>
    </ClaimType>
    <!-- 其他ClaimType定义 -->
  </ClaimsSchema>
</BuildingBlocks>

4. 验证用户旅程中Claims的持续性

检查用户旅程X-SignIn的编排步骤,确保后续的AAD用户读取/写入步骤不会清除或覆盖groups Claim。例如,AAD-UserReadUsingAlternativeSecurityId-NoError等技术配置文件的<OutputClaims>中不要包含groups,避免覆盖从IdP获取的值。

验证

修改配置后重新上传策略,通过SAML追踪器检查最终发送给SP的断言,确认groups Claim已成功包含在其中。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:37:02