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

如何配置AAD B2C仅登录自定义策略支持本地账户及第三方客户端

AAD B2C 仅登录自定义策略配置方案

1. 仅邮箱输入UI配置

是的,用**自断言技术配置文件(Self-Asserted TP)**实现。你需要定义一个只包含email输入字段的自断言页面,隐藏所有注册相关选项,示例配置片段:

<TechnicalProfile Id="SelfAsserted-EmailInput">
  <DisplayName>Enter Email</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
    <Item Key="setting.showSignupLink">false</Item> <!-- 隐藏注册链接 -->
  </Metadata>
  <InputClaims />
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="email" Required="true" />
  </OutputClaims>
  <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>

2. 邮箱域名映射IdP(无需外部REST)

可以用ClaimsTransformation结合预定义的域名映射字典实现,完全在策略引擎内完成判断:

  • 先通过ExtractDomain提取邮箱的域名部分
  • 再用LookupString根据域名匹配对应的IdP标识符

示例配置:

<!-- 提取邮箱域名 -->
<ClaimsTransformation Id="ExtractEmailDomain" TransformationMethod="ExtractDomain">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="emailAddress" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="domain" TransformationClaimType="domain" />
  </OutputClaims>
</ClaimsTransformation>

<!-- 域名到IdP的映射规则 -->
<ClaimsTransformation Id="MapDomainToIdP" TransformationMethod="LookupString">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="domain" TransformationClaimType="inputParameter" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="mycompany.com" DataType="string" Value="LocalAccount" />
    <InputParameter Id="gmail.com" DataType="string" Value="Google" />
    <InputParameter Id="outlook.com" DataType="string" Value="AzureAD" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="selectedIdP" TransformationClaimType="outputClaim" />
  </OutputClaims>
</ClaimsTransformation>

将这两个转换逻辑绑定到自断言TP的OutputClaimsTransformations中,就能得到selectedIdP声明用于后续跳转。

3. 根据IdP跳转对应登录流程

用Orchestration Step结合ClaimsProviderSelection实现动态分支:

  • 先执行邮箱输入和域名映射步骤
  • 新增编排步骤,根据selectedIdP的值匹配对应的登录流程

示例:

<OrchestrationStep Order="1" Type="ClaimsExchange">
  <ClaimsExchanges>
    <ClaimsExchange Id="EmailInputExchange" TechnicalProfileReferenceId="SelfAsserted-EmailInput" />
  </ClaimsExchanges>
</OrchestrationStep>

<OrchestrationStep Order="2" Type="ClaimsExchange">
  <ClaimsExchanges>
    <ClaimsExchange Id="ExtractDomainExchange" TechnicalProfileReferenceId="TP-ExtractDomain" />
    <ClaimsExchange Id="MapDomainToIdPExchange" TechnicalProfileReferenceId="TP-MapDomainToIdP" />
  </ClaimsExchanges>
</OrchestrationStep>

<OrchestrationStep Order="3" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
  <ClaimsProviderSelections>
    <ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountLoginExchange" ClaimType="selectedIdP" Operator="Equal" Value="LocalAccount" />
    <ClaimsProviderSelection TargetClaimsExchangeId="GoogleLoginExchange" ClaimType="selectedIdP" Operator="Equal" Value="Google" />
    <ClaimsProviderSelection TargetClaimsExchangeId="AzureADLoginExchange" ClaimType="selectedIdP" Operator="Equal" Value="AzureAD" />
  </ClaimsProviderSelections>
</OrchestrationStep>

<!-- 各IdP对应的登录步骤 -->
<OrchestrationStep Order="4" Type="ClaimsExchange">
  <ClaimsExchanges>
    <ClaimsExchange Id="LocalAccountLoginExchange" TechnicalProfileReferenceId="LocalAccount-UsernamePassword" />
    <ClaimsExchange Id="GoogleLoginExchange" TechnicalProfileReferenceId="Google-OAUTH" />
    <ClaimsExchange Id="AzureADLoginExchange" TechnicalProfileReferenceId="AzureAD-OIDC" />
  </ClaimsExchanges>
</OrchestrationStep>

4. 本地账户管理员组强制MFA

需要先读取用户组信息,再判断是否触发MFA:

  • 用AAD-UserReadUsingEmailAddress读取用户所属组ID
  • 用CompareClaimToValue判断是否属于管理员组
  • 编排步骤中根据判断结果决定是否执行MFA流程

示例:

<!-- 读取用户组信息 -->
<TechnicalProfile Id="AAD-UserReadUsingEmailAddress">
  <Metadata>
    <Item Key="Operation">Read</Item>
    <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="objectId" />
    <OutputClaim ClaimTypeReferenceId="displayName" />
    <OutputClaim ClaimTypeReferenceId="givenName" />
    <OutputClaim ClaimTypeReferenceId="surname" />
    <OutputClaim ClaimTypeReferenceId="groups" /> <!-- 获取用户组列表 -->
  </OutputClaims>
  <IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>

<!-- 判断是否为管理员组 -->
<ClaimsTransformation Id="IsAdmin" TransformationMethod="CompareClaimToValue">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="groups" TransformationClaimType="inputClaim" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="compareTo" DataType="string" Value="管理员组ObjectID" />
    <InputParameter Id="operator" DataType="string" Value="contains" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="isAdmin" TransformationClaimType="outputClaim" />
  </OutputClaims>
</ClaimsTransformation>

<!-- 编排步骤中的MFA分支 -->
<OrchestrationStep Order="5" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
      <Value>selectedIdP</Value>
      <Value>LocalAccount</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="UserReadExchange" TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress" />
    <ClaimsExchange Id="CheckAdminExchange" TechnicalProfileReferenceId="TP-CheckIsAdmin" />
  </ClaimsExchanges>
</OrchestrationStep>

<OrchestrationStep Order="6" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
      <Value>isAdmin</Value>
      <Value>true</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="MFAExchange" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" />
  </ClaimsExchanges>
</OrchestrationStep>

5. 第三方IdP配置

在自定义策略的<ClaimsProviders>节点下添加对应IdP的声明提供程序,配置OAuth/OIDC协议的技术配置文件,确保返回email、displayName等所需声明即可,无需额外存储逻辑。

6. 颁发JWT令牌

在<RelyingParty>节点中定义需要返回给依赖方的声明:

<RelyingParty>
  <DefaultUserJourney ReferenceId="SignInOnlyJourney" />
  <TechnicalProfile Id="PolicyProfile">
    <DisplayName>PolicyProfile</DisplayName>
    <Protocol Name="OpenIdConnect" />
    <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="email" />
      <OutputClaim ClaimTypeReferenceId="displayName" />
      <OutputClaim ClaimTypeReferenceId="givenName" />
      <OutputClaim ClaimTypeReferenceId="surname" />
      <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="UserId" />
    </OutputClaims>
    <SubjectNamingInfo ClaimType="objectId" />
  </TechnicalProfile>
</RelyingParty>

关键注意事项

  • 所有自定义策略需基于AAD B2C基础策略文件(TrustFrameworkBase.xml、TrustFrameworkExtensions.xml)扩展
  • 本地账户需预先通过邀请或批量导入方式在AAD B2C中创建,无需配置注册流程
  • 测试时可使用B2C内置的策略测试工具,验证每个步骤的声明流转是否符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:50:23