Search code examples
azure-ad-b2cidentity-experience-framework

How can I get a forgot password link on a custom Sign In policy for local accounts?


Using AAD B2C identity experience framework, I am trying to create a custom policy that allows sign-in to a local AADB2C account and includes a "Can’t access your account?" link invoking the built-in self-service functionality. So basically I want the user experience/functionality of the built-in "B2C_1_SignIn_Local" policy, but as part of my suite of custom policies. I do NOT want this userjourney/experience to allow the user to choose a different IdP.

I have been able to create a userjourney that invokes a local sign-in, but the UI doesn't include the "Can’t access your account?" link. The userjourney I have so far looks like this:

 <UserJourney Id="SignInB2CLocal">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection TargetClaimsExchangeId="SignInWithLogonNameExchange" />
          </ClaimsProviderSelections>
        </OrchestrationStep>

       <OrchestrationStep Order="2" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="SignInWithLogonNameExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
        </ClaimsExchanges>
       </OrchestrationStep>


        <OrchestrationStep Order="3" 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="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
    </UserJourney>

The above is based on a combination of what I found in the built-in policy B2C_1_SignIn_Local (downloaded file) and what I used for other IdPs like AAD. I also tried directly calling the built-in B2C_1_SignIn_Local from my MVC ASP.NET application but got token validation errors.

Is my intended result possible?

thanks!

Martin


Solution

  • You can either:

    (i) Change from the ClaimsProviderSelection and ClaimsExchange orchestration steps to the CombinedSignInAndSignUp one with the api.signuporsignin content definition, or

    (ii) Change from the api.selfasserted content definition to the api.signuporsignin one for the SelfAsserted-LocalAccountSignin-Email technical profile.

    What is important is the <DataUri /> value for the content definition is set to:

    urn:com:microsoft:aad:b2c:elements:unifiedssp:1.0.0
    

    which renders the "Forgot your password" and "Sign up now" links.

    i) The CombinedSignInAndSignUp orchestration step

    <OrchestrationSteps>
      <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signupsignin">
        <ClaimsProviderSelections>
          <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
        </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="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="3" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
    </OrchestrationSteps>
    

    ii) The LocalAccountSigninEmailExchange technical profile

    <TechnicalProfiles>
      <TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
        <Metadata>
          <Item Key="ContentDefinitionReferenceId">api.signuporsignin</Item>
        </Metadata>
      </TechnicalProfile>
    </TechnicalProfiles>
    
    <OrchestrationSteps>
      <OrchestrationStep Order="1" Type="ClaimsExchange">
        <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="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="3" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
    </OrchestrationSteps>