如何修复AADB2C90304错误:编排步骤2中找不到指定Claims Exchange
问题描述
我通过以下代码使用Microsoft Graph API创建用户:
var userToAddToAAD = new User { AccountEnabled = true, DisplayName = $"{firstName} {lastName}", MailNickname = $"{firstName}{lastName[0]}", PasswordProfile = new PasswordProfile { ForceChangePasswordNextSignIn = true, Password = password }, Identities = new List<ObjectIdentity> { new ObjectIdentity { SignInType = "emailAddress", Issuer = _issuer, IssuerAssignedId = emailAddress, } } }; var scopes = new[] { "https://graph.microsoft.com/.default" }; var clientSecretCredential = new ClientSecretCredential(_tenantId, _testboltDevClientApiClientId, _testboltDevClientApiClientSecret); var graphClient = new GraphServiceClient(clientSecretCredential, scopes); var newUser = await graphClient.Users.PostAsync(userToAddToAAD);
为实现新用户登录后触发密码重置流程,我创建了如下自定义策略:
<UserJourney Id="CustomSignin"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin.custom"> <ClaimsProviderSelections> <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> <Precondition Type="ClaimsExist" ExecuteActionsIf="true"> <!-- Skip this step if change password is required. --> <Value>forceChangePasswordNextLogin</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" /> <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" /> </ClaimsExchanges> </OrchestrationStep> <!-- This step reads any user attributes that we may not have received when in the token. --> <OrchestrationStep Order="3" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="false"> <Value>forceChangePasswordNextLogin</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <!--Force password reset upon password expiration--> <ClaimsExchange Id="ForcePasswordResetUponPasswordExpiration" TechnicalProfileReferenceId="SelfAsserted-ForcePasswordReset-ExpiredPassword" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="4" Type="InvokeSubJourney"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="false"> <Value>isForgotPassword</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <JourneyList> <Candidate SubJourneyReferenceId="ResetPassword" /> </JourneyList> </OrchestrationStep> <!-- This step reads any user attributes that we may not have received when in the token. --> <OrchestrationStep Order="5" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="true"> <Value>authenticationSource</Value> <Value>socialIdpAuthentication</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> <ClientDefinition ReferenceId="DefaultWeb" /> </UserJourney> <UserJourney Id="ProfileEdit"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections"> <ClaimsProviderSelections> <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" /> </ClaimsProviderSelections> </OrchestrationStep> <OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsProviderSelections> <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" /> </ClaimsProviderSelections> <ClaimsExchanges> <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="3" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="4" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="B2CUserProfileUpdateExchange" TechnicalProfileReferenceId="SelfAsserted-ProfileUpdate" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> <ClientDefinition ReferenceId="DefaultWeb" /> </UserJourney>
配置后,用户登录可正常跳转至密码重置页面并完成更新,但之后出现错误:AADB2C90304: Claims exchange with id 'LocalAccountSigninEmailExchange' could not be found in orchestration step '2'
问题原因
- ProfileEdit用户旅程XML结构非法:
ProfileEdit的步骤2类型为ClaimsExchange,但该类型的编排步骤不允许包含<ClaimsProviderSelections>元素,这个无效配置会导致B2C策略解析异常,进而触发错误提示。 - 流程逻辑触发异常跳转:策略解析异常可能导致密码重置完成后,流程错误进入步骤2,而该步骤未定义
LocalAccountSigninEmailExchange这个Claims Exchange,从而引发报错。
修复步骤
1. 修正ProfileEdit用户旅程的步骤2
移除步骤2中的<ClaimsProviderSelections>元素(ClaimsExchange类型步骤仅支持<ClaimsExchanges>元素),修改后代码如下:
<OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" /> </ClaimsExchanges> </OrchestrationStep>
2. 验证CustomSignin流程逻辑
确认CustomSignin步骤2的前置条件逻辑正常:
- 第一个前置条件检查
objectId是否存在,存在则跳过步骤2(用户完成登录/密码重置后必然存在objectId,此逻辑可确保流程不会进入步骤2)。 - 第二个前置条件检查
forceChangePasswordNextLogin是否存在,存在则跳过步骤2,确保强制改密码流程不会进入步骤2。
测试验证
修改完成后重新上传自定义策略,执行以下测试:
- 创建新用户并登录,确认强制改密码流程正常触发。
- 完成密码重置后,确认流程可正常跳转至后续步骤,不再出现
AADB2C90304错误。
内容的提问来源于stack exchange,提问作者Piyumi Nadeeshani
相关产品推荐
相关产品推荐

