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

如何修复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'


问题原因

  1. ProfileEdit用户旅程XML结构非法:ProfileEdit的步骤2类型为ClaimsExchange,但该类型的编排步骤不允许包含<ClaimsProviderSelections>元素,这个无效配置会导致B2C策略解析异常,进而触发错误提示。
  2. 流程逻辑触发异常跳转:策略解析异常可能导致密码重置完成后,流程错误进入步骤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。

测试验证

修改完成后重新上传自定义策略,执行以下测试:

  1. 创建新用户并登录,确认强制改密码流程正常触发。
  2. 完成密码重置后,确认流程可正常跳转至后续步骤,不再出现AADB2C90304错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:22:04