1

I have a user invitation custom policy, user will get an email with a link and that link will have a token. My requirement is I want to show two options to user:

  1. Change password
  2. Login with Other providers

Below is my user journey,

<UserJourneys>
<UserJourney Id="SignInWithInvitationLink">
  <OrchestrationSteps>
    
    <OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />

    <OrchestrationStep Order="2" Type="ClaimsExchange">
     <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>email</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>        
      <ClaimsExchanges>
        <ClaimsExchange Id="SelfAsserted-Unsolicited" TechnicalProfileReferenceId="SelfAsserted-Unsolicited" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadUsingEmailAddress" TechnicalProfileReferenceId="AAD-UserInvitationStatusReadUsingEmailAddress"/>
      </ClaimsExchanges>
    </OrchestrationStep>

    <OrchestrationStep Order="4" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="Copy-UPN" TechnicalProfileReferenceId="CopyUserUPN"/>
      </ClaimsExchanges>
    </OrchestrationStep>

    <OrchestrationStep Order="5" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>userPrincipalName</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="SelfAssertedUserNotFound" TechnicalProfileReferenceId="SelfAsserted-UserNotFound" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <OrchestrationStep Order="6" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>extension_isinvitationaccepted</Value>
          <Value>True</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsProviderSelections>
        <ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountChangePassword"/>
        <ClaimsProviderSelection TargetClaimsExchangeId="AzureADExchangeWithAADtoken"/>
      </ClaimsProviderSelections>
    </OrchestrationStep>

    <OrchestrationStep Order="7" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>extension_isinvitationaccepted</Value>
          <Value>True</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountChangePassword" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingUPN" />
        <ClaimsExchange Id="AzureADExchangeWithAADtoken" TechnicalProfileReferenceId="EmailValidator"/>
      </ClaimsExchanges>
    </OrchestrationStep>

      <OrchestrationStep Order="8" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>provider</Value>
            <Value>Microsoft</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserLogin" TechnicalProfileReferenceId="AzureADProfile_issueAADtoken"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="9" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>provider</Value>
            <Value>Google</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="GoogleUserLogin" TechnicalProfileReferenceId="Google-OAuth2"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="10" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>          
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>provider</Value>
            <Value>Facebook</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="FacebookLogin" TechnicalProfileReferenceId="Facebook-OAUTH"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <!-- For external IDP authentication, attempt to find the user account in the directory. -->
      <OrchestrationStep Order="11" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</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="12" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="13" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>authenticationSource</Value>
            <Value>socialIdpAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithEmailAddress" TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="14" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="15" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
            <Value>extension_isinvitationaccepted</Value>
            <Value>True</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>authenticationSource</Value>
            <Value>socialIdpAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountChangeInvitationStatus" TechnicalProfileReferenceId="LocalAccountWriteInvitationStatusUsingUPN"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="16" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
            <Value>email</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>authenticationSource</Value>
            <Value>socialIdpAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithSocialEmailAddress" TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="17" Type="ClaimsExchange">
        <Preconditions>
          <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
            <Value>signInNames.emailAddress</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
          <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>authenticationSource</Value>
            <Value>socialIdpAuthentication</Value>
            <Action>SkipThisOrchestrationStep</Action>
          </Precondition>
        </Preconditions>
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserReadWithSignInEmailAddress" TechnicalProfileReferenceId="AAD-UserReadUsingSignInEmailAddress"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="18" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="CreateCustomerMapping" TechnicalProfileReferenceId="REST-CreateCustomerUserMappingInvitation"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="19" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="GetCurrentUserTime" TechnicalProfileReferenceId="GetCurrentTime"/>
        </ClaimsExchanges>
      </OrchestrationStep>

      <OrchestrationStep Order="20" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="AADUserWriteLastLogin" TechnicalProfileReferenceId="AAD-UserWriteLastLogin"/>
        </ClaimsExchanges>
      </OrchestrationStep>

    <OrchestrationStep Order="21" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer"/>

  </OrchestrationSteps>
  <ClientDefinition ReferenceId="DefaultWeb"/>
</UserJourney>

Now, my problem is when I open the link in email B2C showing a generic error message like "something went wrong". Orchestration step 6 is allowing the user to choose whether password change or use other providers. I used application insights and got the following error:

{
"Kind": "FatalException",
"Content": {
  "Time": "6:47 PM",
  "Exception": {
    "Kind": "Handled",
    "HResult": "80131509",
    "Message": "Claims exchange with id 'AADUserReadUsingEmailAddress' could not be found in orchestration step '7' and the step contains more than one claims exchange.",
    "Data": {}
  }
}

}

Alex
  • 734
  • 6
  • 29

1 Answers1

0

The reason for this error maybe because you might have written User Journey ID in two files both Base/Extension and Relying Party Policy. Try to change the id to something else in one of the files if one of the id is same in both files(try to avoid duplicate user journey). or try moving the userjourney to next step or after base files steps are over.

If the count of steps and ClaimsExchange ID is unique, then only it will accept otherwise it will treat it as different ClaimsExchange and error will occur .

References:

  1. Azure AD B2C Custom Policy - Stack Overflow
  2. Local and Social Account Sign policy with split email verification and sign up - Stack Overflow
  3. microsoft graph api - Azure AD B2C: Cannot login immediately after going through a Password Reset Flow - Stack Overflow
kavyaS
  • 8,026
  • 1
  • 7
  • 19
  • "SignInWithInvitationLink", is the user journey id and is not duplicated in any of the other files, but the ClaimExchangeId "AzureADExchangeWithAADtoken" was in another journey so I changed the Id. But no luck I'm getting the same error. – Alex Mar 23 '22 at 07:47
  • Hi @Alex ! Have you tried moving that user journey to any of the next steps ? – kavyaS Apr 01 '22 at 14:14
  • I'm getting the error screen when I try to load the policy in the browser, no steps are shown to me. – Alex Apr 04 '22 at 07:51