调整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>
关键修改说明
拆分本地账户注册流程
- 将原步骤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,通过前置条件自动匹配场景。
- 移除原步骤7的用户创建逻辑,新增步骤8作为统一的用户创建节点,仅在
调整TOTP步骤顺序
- TOTP依赖目录中已存在的用户对象,因此将原步骤8、9移至用户创建步骤(步骤8)之后,确保TOTP操作时用户已存在。
优化前置条件
- 验证步骤(新步骤7)仅对未创建的新用户执行,已存在的用户直接跳过。
- 用户创建步骤(新步骤8)仅在验证通过后执行,避免未验证用户进入目录。
内容的提问来源于stack exchange,提问作者Andrew Wiebe
相关产品推荐
相关产品推荐

