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

调整Azure B2C自定义策略:验证完成后再创建用户对象

Azure B2C自定义策略调整方案:验证通过后再创建用户

要实现仅在自定义信息验证通过后才创建用户对象,核心是将用户目录写入操作(本地/社交账户创建)从验证步骤前移至验证步骤后,同时拆分本地账户的注册流程,先收集凭证再验证,最后创建用户。以下是调整后的用户旅程配置及关键说明:

修改后的完整用户旅程配置

<UserJourney Id="SignUpOrSignIn_Custom">
  <OrchestrationSteps>

    <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
      <ClaimsProviderSelections>
        <ClaimsProviderSelection TargetClaimsExchangeId="GoogleExchange" />
        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
        <ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange" />
      </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="GoogleExchange" TechnicalProfileReferenceId="Google-OAuth2" />
        <!-- 替换为仅收集邮箱和密码的自断言技术配置,不创建用户 -->
        <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignUp-CollectCredentials" />
        <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <OrchestrationStep Order="3" Type="InvokeSubJourney">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>isForgotPassword</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <JourneyList>
        <Candidate SubJourneyReferenceId="PasswordReset" />
      </JourneyList>
    </OrchestrationStep>

    <!-- 社交登录:检查用户是否已存在 -->
    <OrchestrationStep Order="4" 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="5" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>authenticationSource</Value>
          <Value>localAccountAuthentication</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- 已存在用户:读取用户属性 -->
    <OrchestrationStep Order="6" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- 新用户:执行自定义信息验证 -->
    <OrchestrationStep Order="7" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>extension_empOPRID</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountSignUpWithLogonEmail-ValidateData" TechnicalProfileReferenceId="Get-Validate-Personal-Data" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- 验证通过后:创建本地/社交用户 -->
    <OrchestrationStep Order="8" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>extension_empOPRID</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <!-- 本地账户创建 -->
        <ClaimsExchange Id="AADUserWriteLocal" TechnicalProfileReferenceId="AAD-UserWriteUsingLogonEmail" />
        <!-- 社交账户创建 -->
        <ClaimsExchange Id="AADUserWriteSocial" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- TOTP注册(依赖已存在的用户对象) -->
    <OrchestrationStep Order="9" Type="InvokeSubJourney">
      <JourneyList>
        <Candidate SubJourneyReferenceId="TotpFactor-Input" />
      </JourneyList>
    </OrchestrationStep>
    
    <!-- TOTP验证 -->
    <OrchestrationStep Order="10" Type="InvokeSubJourney">
      <JourneyList>
        <Candidate SubJourneyReferenceId="TotpFactor-Verify" />
      </JourneyList>
    </OrchestrationStep>

    <!-- 颁发令牌 -->
    <OrchestrationStep Order="11" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

  </OrchestrationSteps>
  <ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>

关键修改说明

  1. 拆分本地账户注册流程

    • 将原步骤2中的LocalAccountSignUpWithLogonEmail替换为自定义的SelfAsserted-LocalAccountSignUp-CollectCredentials技术配置文件,该配置仅收集用户邮箱和密码,不执行目录写入操作。示例配置参考:
      <TechnicalProfile Id="SelfAsserted-LocalAccountSignUp-CollectCredentials">
        <DisplayName>Local Account Sign Up</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.localaccountsignup</Item>
        </Metadata>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
          <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
          <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
        </OutputClaims>
        <ValidationTechnicalProfiles>
          <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" Enabled="false" />
        </ValidationTechnicalProfiles>
      </TechnicalProfile>
      
  2. 延迟用户写入操作

    • 移除原步骤7的用户创建逻辑,新增步骤8作为统一的用户创建节点,仅在extension_empOPRID(验证通过后的声明)存在且用户未创建(无objectId)时执行。
    • 针对本地账户使用AAD-UserWriteUsingLogonEmail,社交账户使用AAD-UserWriteUsingAlternativeSecurityId,通过前置条件自动匹配场景。
  3. 调整TOTP步骤顺序

    • TOTP依赖目录中已存在的用户对象,因此将原步骤8、9移至用户创建步骤(步骤8)之后,确保TOTP操作时用户已存在。
  4. 优化前置条件

    • 验证步骤(新步骤7)仅对未创建的新用户执行,已存在的用户直接跳过。
    • 用户创建步骤(新步骤8)仅在验证通过后执行,避免未验证用户进入目录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:05:35