微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Azure AD B2C:通过密码重置流程后无法立即登录

如何解决Azure AD B2C:通过密码重置流程后无法立即登录

我们创建了一个内置的密码重置用户流程。

我们使用 Microsoft Graph API 在 B2C 中自动注册用户,并发送一封电子邮件,其中包含指向密码重置流程的直接链接,以便他们在首次登录时重置密码。

用户正确地通过密码重置用户流程,然后重定向回我们的应用程序,该应用程序将用户重定向到我们的 SignIn 自定义策略用户旅程!

我们有 Home Realm discovery,用户首先会看到一个屏幕来输入他们的电子邮件地址,点击下一步,然后输入密码。

输入电子邮件地址并单击“下一步”后,我们收到以下错误

Sorry,but we're having trouble signing you in.
We track these errors automatically,but if the problem persists feel free to contact us. In the meantime,please try again.

Correlation ID: d5a7e1ed-a6d2-4b6d-bc87-b8612a5419b4

Timestamp: 2021-05-27 12:19:05Z

AADB2C: An exception has occurred.

这是 Userjourney 和 Subjourney

<Userjourneys>
<Userjourney Id="HRDSignUpSignInMFAEmebeddedPasswordReset">
  <orchestrationSteps>

    <orchestrationStep Order="1" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="ParseDomainHint" TechnicalProfileReferenceId="ParseDomainHint" />
      </ClaimsExchanges>
    </orchestrationStep>

    <!-- api.hrd reference to custom login page / content deFinition -->
    <orchestrationStep Order="2" Type="ClaimsExchange" ContentDeFinitionReferenceId="api.hrd">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="SigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-Signin-Email" />
      </ClaimsExchanges>
    </orchestrationStep>

    <orchestrationStep Order="3" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>False</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="IsKNownCustomerLogic" TechnicalProfileReferenceId="CreateidentityProvidersCollectionLogic" />
      </ClaimsExchanges>
    </orchestrationStep>

    <!-- The technical profile uses a validation technical profile to authenticate the user. -->
    <!--Protocal: Web.TPEngine.Providers.SelfAssertedAttributeProvider Session: SM-AAD=Web.TPEngine.SSO.DefaultSSOSessionProvider -->
    <orchestrationStep Order="4" Type="CombinedSignInAndSignUp" ContentDeFinitionReferenceId="api.signinandsignupwithpassword">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsProviderSelections>
        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
        <ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange" />
      </ClaimsProviderSelections>
      <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
      </ClaimsExchanges>
    </orchestrationStep>

    <!-- Local Email Account Sign Up -->
    <!-- Protocol: Web.TPEngine.Providers.SelfAssertedAttributeProvider  Session: SM-AAD="Web.TPEngine.SSO.DefaultSSOSessionProvider -->
    <orchestrationStep Order="5" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="SignUpWithlogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithlogonEmail" />
        <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" />
      </ClaimsExchanges>
    </orchestrationStep>

    <!-- If the domain matched any kNown domain,then this step will have a single IdP
            enabled due to each kNown IdP TP having an enablement flag via identityProviders claim -->
    <orchestrationStep Order="6" Type="ClaimsProviderSelection" ContentDeFinitionReferenceId="api.idpselections">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsProviderSelections>
        <ClaimsProviderSelection TargetClaimsExchangeId="IDP1OIDC" />
        <ClaimsProviderSelection TargetClaimsExchangeId="IDP2SAML" />
      </ClaimsProviderSelections>
    </orchestrationStep>

    <orchestrationStep Order="7" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="IDP1OIDC" TechnicalProfileReferenceId="IDP1-OIDC-TP" />
        <ClaimsExchange Id="IDP2SAML" TechnicalProfileReferenceId="IDP2-SAML-TP" />
      </ClaimsExchanges>
    </orchestrationStep>

     <!-- If the user clicks on Forgot Password then execute this subjourney - otherwise skip -->
     <orchestrationStep Order="8" Type="InvokeSubjourney">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>isForgotPassword</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <journeyList>
        <Candidate SubjourneyReferenceId="PasswordReset" />
      </journeyList>
    </orchestrationStep>

    <!-- For social IDP authentication,attempt to find the user account in the directory. -->
    <orchestrationStep Order="9" 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="AADUserReadUsingalternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingalternativeSecurityId-NoError" />
      </ClaimsExchanges>
    </orchestrationStep>

    <orchestrationStep Order="10" 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>
    <!-- The prevIoUs step (SelfAsserted-Social) Could have been skipped if there were no attributes to collect 
         from the user. So,in that case,create the user in the directory if one does not already exist 
         (verified using objectId which would be set from the last step if account was created in the directory. -->
    <orchestrationStep Order="11" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>authenticationSource</Value>
          <Value>socialIdpAuthentication</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingalternativeSecurityId" />
      </ClaimsExchanges>
    </orchestrationStep>
    <orchestrationStep Order="12" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>isActiveMFASession</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" />
      </ClaimsExchanges>
    </orchestrationStep>
    <!-- Save MFA phone number: The precondition verifies whether the user provided a new number in the 
            prevIoUs step. If so,then the phone number is stored in the directory for future authentication 
            requests. -->
    <!--References AAD-Common(Web.TPEngine.Providers.AzureActiveDirectoryProvider & SM-Noop) -->
    <orchestrationStep Order="13" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>isFederatedAuthentication</Value>
          <Value>true</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>newPhoneNumberEntered</Value>
          <Action>SkipThisorchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneNumberUsingObjectId" />
      </ClaimsExchanges>
    </orchestrationStep>
    <orchestrationStep Order="14" Type="ClaimsExchange">
      <ClaimsExchanges>
        <!-- create the emails claim combining signInNames and otherMails -->
        <ClaimsExchange Id="AADUserCreateEmailsClaim" TechnicalProfileReferenceId="AAD-UserCreateEmailsClaim" />
      </ClaimsExchanges>
    </orchestrationStep>
    <orchestrationStep Order="15" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
  </orchestrationSteps>
  <ClientDeFinition ReferenceId="DefaultWeb" />
</Userjourney>
<Subjourneys>
    <Subjourney Id="PasswordReset" Type="Call">
      <orchestrationSteps>
        <!--Sample: Validate user's email address. Run this step only when user resets the password-->
        <orchestrationStep Order="1" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountdiscoveryUsingEmailAddress" />
          </ClaimsExchanges>
        </orchestrationStep>
        <!--Sample: Collect and persist a new password. Run this step only when user resets the password-->
        <orchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
          </ClaimsExchanges>
        </orchestrationStep>
      </orchestrationSteps>
    </Subjourney>
  </Subjourneys>

解决方法

不是完整的答案/修复。

我不知道上面的用户旅程有什么问题,但是根据@JasSuri-MSFT 在这里写的https://github.com/azure-ad-b2c/samples/issues/235 错误消息说:

Claims exchange with id 'LocalAccountSigninEmailExchange' could not be found 
in orchestration step '5' and the step contains more than one claims exchange.

然后我所做的就是将 <ClaimExchange>LocalAccountSigninEmailExchange 从第 4 步移到第 5 步。现在第 4 步和第 5 步如下所示:

 <!-- The technical profile uses a validation technical profile to authenticate the user. -->
        <!--Protocal: Web.TPEngine.Providers.SelfAssertedAttributeProvider Session: SM-AAD=Web.TPEngine.SSO.DefaultSSOSessionProvider -->
        <OrchestrationStep Order="4" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signinandsignupwithpassword">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
              <Value>isFederatedAuthentication</Value>
              <Value>true</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsProviderSelections>
            <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
            <ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange" />
          </ClaimsProviderSelections>
          <ClaimsExchanges>
            <!-- <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" /> -->
          </ClaimsExchanges>
        </OrchestrationStep>
        <!-- Local Email Account Sign Up -->
        <!-- Protocol: Web.TPEngine.Providers.SelfAssertedAttributeProvider  Session: SM-AAD="Web.TPEngine.SSO.DefaultSSOSessionProvider -->
        <OrchestrationStep Order="5" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
              <Value>isFederatedAuthentication</Value>
              <Value>true</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
            <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
            <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" />
          </ClaimsExchanges>
        </OrchestrationStep>

这与用户指南和 Github 中的 B2C 示例不同,但出于某种原因现在可以使用。也就是说,我的信心很低,因为我不明白为什么,但我想我还是会和你分享。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。