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

Azure AD B2C自定义策略无密码注册登录流程修改咨询

Azure AD B2C 无密码自定义策略(邮箱/手机号二选一)改造方案

一、核心改造方向

基于拆分验证页的示例策略,重点完成以下调整:

  • 新增身份选择逻辑,支持用户选择邮箱或手机号发起OTP验证
  • 动态控制信息收集页面字段:验证邮箱则收集手机号,验证手机号则收集邮箱
  • 移除所有密码相关的用户旅程、技术配置与页面元素
  • 统一注册/登录的OTP验证流程,复用核心技术配置

二、注册流程改造步骤

1. 定义身份选择声明与页面

在<BuildingBlocks>的<ClaimsSchema>中添加身份类型声明:

<ClaimType Id="identityType">
  <DisplayName>验证方式</DisplayName>
  <DataType>string</DataType>
  <UserInputType>RadioSingleSelect</UserInputType>
  <Restriction>
    <Enumeration Text="邮箱" Value="email" SelectByDefault="false" />
    <Enumeration Text="手机号" Value="phone" SelectByDefault="false" />
  </Restriction>
</ClaimType>

创建身份选择页面:

<ContentDefinition Id="api.selfasserted.localaccountsignup.identitytype">
  <LoadUri>~/tenant/templates/AzureBlue/selfAsserted.cshtml</LoadUri>
  <RecoveryUri>~/common/default_page_error.html</RecoveryUri>
  <DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri>
  <Metadata>
    <Item Key="DisplayName">选择验证方式</Item>
  </Metadata>
</ContentDefinition>

2. 分支触发OTP验证

在注册用户旅程中,添加身份选择步骤后,根据identityType的值分支执行邮箱/手机号OTP验证:

<UserJourney Id="SignUp">
  <OrchestrationSteps>
    <!-- 步骤1:选择身份类型 -->
    <OrchestrationStep Order="1" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="IdentityTypeExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignUp-IdentityType" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 步骤2:手机号OTP验证分支 -->
    <OrchestrationStep Order="2" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>identityType</Value>
          <Value>email</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="PhoneVerificationExchange" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 步骤3:邮箱OTP验证分支 -->
    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>identityType</Value>
          <Value>phone</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="EmailVerificationExchange" TechnicalProfileReferenceId="EmailVerification-InputOrVerify" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 步骤4:补全个人信息 -->
    <OrchestrationStep Order="4" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="SignUpProfileExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignUp-Profile" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 后续创建用户、颁发令牌步骤保持不变 -->
  </OrchestrationSteps>
</UserJourney>

3. 动态控制信息收集字段

修改SelfAsserted-LocalAccountSignUp-Profile技术配置,根据identityType隐藏已验证字段,显示互补字段:

<TechnicalProfile Id="SelfAsserted-LocalAccountSignUp-Profile">
  <DisplayName>补全个人信息</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>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="identityType" />
    <InputClaim ClaimTypeReferenceId="email" />
    <InputClaim ClaimTypeReferenceId="phoneNumber" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="givenName" Required="true" DisplayName="名字" />
    <OutputClaim ClaimTypeReferenceId="surname" Required="true" DisplayName="姓氏" />
    <OutputClaim ClaimTypeReferenceId="country" Required="true" DisplayName="国籍" />
    <OutputClaim ClaimTypeReferenceId="passportNumber" Required="true" DisplayName="护照号" />
    <!-- 动态显示手机号(验证邮箱时显示) -->
    <OutputClaim ClaimTypeReferenceId="phoneNumber" Required="true">
      <DisplayControl>
        <DisplayClaim ClaimTypeReferenceId="phoneNumber" ControlClaimType="PhoneNumber">
          <PredicateValidationReference Id="PhoneNumber" />
        </DisplayClaim>
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>identityType</Value>
            <Value>phone</Value>
            <Action>Hide</Action>
          </Precondition>
        </Preconditions>
      </DisplayControl>
    </OutputClaim>
    <!-- 动态显示邮箱(验证手机号时显示) -->
    <OutputClaim ClaimTypeReferenceId="email" Required="true">
      <DisplayControl>
        <DisplayClaim ClaimTypeReferenceId="email" ControlClaimType="Email">
          <PredicateValidationReference Id="Email" />
        </DisplayClaim>
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>identityType</Value>
            <Value>email</Value>
            <Action>Hide</Action>
          </Precondition>
        </Preconditions>
      </DisplayControl>
    </OutputClaim>
  </OutputClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
  </ValidationTechnicalProfiles>
</TechnicalProfile>

三、登录流程改造步骤

1. 改造登录输入页

创建支持邮箱/手机号输入的登录技术配置:

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-EmailPhone">
  <DisplayName>登录</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="signInName" Required="true" DisplayName="邮箱/手机号" />
  </OutputClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Login-EmailPhone-OTP" />
  </ValidationTechnicalProfiles>
</TechnicalProfile>

2. 实现自动识别的OTP验证

创建自动判断邮箱/手机号并触发OTP验证的技术配置:

<TechnicalProfile Id="Login-EmailPhone-OTP">
  <DisplayName>OTP验证</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>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" />
  </InputClaims>
  <OutputClaims />
  <ValidationTechnicalProfiles>
    <!-- 读取邮箱用户信息 -->
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress">
      <Preconditions>
        <Precondition Type="IsEmail" ExecuteActionsIf="true">
          <Value>signInName</Value>
          <Action>IncludeThisValidationTechnicalProfile</Action>
        </Precondition>
      </Preconditions>
    </ValidationTechnicalProfile>
    <!-- 读取手机号用户信息 -->
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingPhoneNumber">
      <Preconditions>
        <Precondition Type="IsPhoneNumber" ExecuteActionsIf="true">
          <Value>signInName</Value>
          <Action>IncludeThisValidationTechnicalProfile</Action>
        </Precondition>
      </Preconditions>
    </ValidationTechnicalProfile>
    <!-- 触发邮箱OTP验证 -->
    <ValidationTechnicalProfile ReferenceId="EmailVerification-InputOrVerify">
      <Preconditions>
        <Precondition Type="ClaimExists" ExecuteActionsIf="true">
          <Value>email</Value>
          <Action>IncludeThisValidationTechnicalProfile</Action>
        </Precondition>
      </Preconditions>
    </ValidationTechnicalProfile>
    <!-- 触发手机号OTP验证 -->
    <ValidationTechnicalProfile ReferenceId="PhoneFactor-InputOrVerify">
      <Preconditions>
        <Precondition Type="ClaimExists" ExecuteActionsIf="true">
          <Value>phoneNumber</Value>
          <Action>IncludeThisValidationTechnicalProfile</Action>
        </Precondition>
      </Preconditions>
    </ValidationTechnicalProfile>
  </ValidationTechnicalProfiles>
</TechnicalProfile>

3. 调整登录用户旅程

替换原密码登录步骤,改为邮箱/手机号OTP验证流程:

<UserJourney Id="SignIn">
  <OrchestrationSteps>
    <!-- 步骤1:输入邮箱/手机号 -->
    <OrchestrationStep Order="1" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="SigninExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-EmailPhone" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 步骤2:OTP验证 -->
    <OrchestrationStep Order="2" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="LoginOTPExchange" TechnicalProfileReferenceId="Login-EmailPhone-OTP" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <!-- 后续颁发令牌步骤保持不变 -->
  </OrchestrationSteps>
</UserJourney>

四、关键注意事项

  • 彻底移除所有密码相关的技术配置(如LocalAccountPasswordLogin)与用户旅程节点
  • 分别测试邮箱注册/登录、手机号注册/登录流程,确保互补字段收集逻辑正常
  • 调整ContentDefinition的UI模板,保持三个步骤页面风格统一

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:18:09