0
votes

Im trying to do seamless-account-migration listed here, since our Passwords are hashed and our users are in DB, https://github.com/azure-ad-b2c/user-migration

We are using a mobile device and got users to migrate from an Database as part of Migration, I followed

1) ROPC Custom Policy https://docs.microsoft.com/en-us/azure/active-directory-b2c/ropc-custom?tabs=app-reg-ga

2) Defined custom attributes https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-custom-attributes

3) Setup a Rest-API on Legacy IDP to return migrationStatus https://docs.microsoft.com/en-us/azure/active-directory-b2c/custom-policy-rest-api-intro

However, I think the ROPC with REST-API is not supported ? because the

ROPC has Protocol Name="OpenIdConnect" vs

SelfAsserted-LocalAccountSignin-Email has Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

and ran into problem of

Invalid technical profile with id "ResourceOwnerPasswordCredentials-OAUTH2" only the protocol handler ""Web.TPEngine.Providers.SelfAssertedAttributeProvider"" can have a ValidationTechnicalProfile

I stumbled upon these and noticed, the seamless migration with Rest API during Sign-In does not apply for ROPC (mobile devices) ? Is that true ?

https://docs.microsoft.com/en-us/azure/active-directory-b2c/self-asserted-technical-profile

https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect-technical-profile

Can someone tell me how do we do migration during SignIn with Rest-API interaction for ROPC grant_type ?

User Journey

<UserJourney Id="ResourceOwnerPasswordCredentials">
  <PreserveOriginalAssertion>false</PreserveOriginalAssertion>
  <OrchestrationSteps>      
    <OrchestrationStep Order="1" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <OrchestrationStep Order="2" Type="ClaimsExchange">
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>
    <OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
  </OrchestrationSteps>
</UserJourney>

and here is the SelfAsserted-LocalAccountSignin-Email Technical Profile via Self Asserted Protocol

as I was not able to Upload ROPC Technical Profile with ValidationTechnicalProfile via OpenIdConnect Protocol as it said the error stated before,

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="extension_isMigrated" />
          </OutputClaims>
          <ValidationTechnicalProfiles>
            <!--Add user migration validation technical profiles before login-NonInteractive -->

            <!-- Populate extension_requireMigration into the claims pipeline -->
            <ValidationTechnicalProfile ReferenceId="Get-requiresMigration-status-signin" ContinueOnError="false" />

            <!-- If extension_requireMigration is true, call the legacy IdP via the REST API -->
            <ValidationTechnicalProfile ReferenceId="REST-ValidateProfile" ContinueOnError="false">
              <Preconditions>
                <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
                  <Value>extension_isMigrated</Value>
                  <Value>True</Value>
                  <Action>SkipThisValidationTechnicalProfile</Action>
                </Precondition>
              </Preconditions>
            </ValidationTechnicalProfile>

            <!-- If the API returned 'tokensuccess', write the new password and unmark the account for migration -->
            <ValidationTechnicalProfile ReferenceId="AAD-WritePasswordAndFlipMigratedFlag" ContinueOnError="false">
              <Preconditions>
                <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
                  <Value>requiresMigration</Value>
                  <Value>False</Value>
                  <Action>SkipThisValidationTechnicalProfile</Action>
                </Precondition>
              </Preconditions>
            </ValidationTechnicalProfile>

            <!-- Initiate a normal logon against Azure AD B2C -->
            <ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
          </ValidationTechnicalProfiles>
        </TechnicalProfile>

The ROPC Technical Profile, ResourceOwnerPasswordCredentials-OAUTH2 I tried to upload is below which failed with said error

    <TechnicalProfile Id="ResourceOwnerPasswordCredentials-OAUTH2">
      <DisplayName>Local Account SignIn</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <Metadata>
        <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">We can't seem to find your account</Item>
        <Item Key="UserMessageIfInvalidPassword">Your password is incorrect</Item>
        <Item Key="UserMessageIfOldPasswordUsed">Looks like you used an old password</Item>
        <Item Key="DiscoverMetadataByTokenIssuer">true</Item>
        <Item Key="ValidTokenIssuerPrefixes">https://sts.windows.net/</Item>
        <Item Key="METADATA">https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration</Item>
        <Item Key="authorization_endpoint">https://login.microsoftonline.com/{tenant}/oauth2/token</Item>
        <Item Key="response_types">id_token</Item>
        <Item Key="response_mode">query</Item>
        <Item Key="scope">email openid</Item>
      </Metadata>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="logonIdentifier" PartnerClaimType="username" Required="true" DefaultValue="{OIDC:Username}" />
        <InputClaim ClaimTypeReferenceId="password" Required="true" DefaultValue="{OIDC:Password}" />
        <InputClaim ClaimTypeReferenceId="grant_type" DefaultValue="password" />
        <InputClaim ClaimTypeReferenceId="scope" DefaultValue="openid" />
        <InputClaim ClaimTypeReferenceId="nca" PartnerClaimType="nca" DefaultValue="1" />
        <InputClaim ClaimTypeReferenceId="client_id" DefaultValue="XXXXXXXXXXXXX" />
        <InputClaim ClaimTypeReferenceId="resource_id" PartnerClaimType="resource" DefaultValue="XXXXXXXXXXX" />
      </InputClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="oid" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" PartnerClaimType="upn" />
        <OutputClaim ClaimTypeReferenceId="extension_isMigrated" />
      </OutputClaims>
      <OutputClaimsTransformations>
        <OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromObjectID" />
      </OutputClaimsTransformations>
      <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
      <ValidationTechnicalProfiles>
        <!--Add user migration validation technical profiles before login-NonInteractive -->

        <!-- Populate extension_requireMigration into the claims pipeline -->
        <ValidationTechnicalProfile ReferenceId="Get-requiresMigration-status-signin" ContinueOnError="false" />

        <!-- If extension_requireMigration is true, call the legacy IdP via the REST API -->
        <ValidationTechnicalProfile ReferenceId="REST-ValidateProfile" ContinueOnError="false">
          <Preconditions>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
              <Value>extension_isMigrated</Value>
              <Value>True</Value>
              <Action>SkipThisValidationTechnicalProfile</Action>
            </Precondition>
          </Preconditions>
        </ValidationTechnicalProfile>

        <!-- If the API returned 'tokensuccess', write the new password and unmark the account for migration -->
        <ValidationTechnicalProfile ReferenceId="AAD-WritePasswordAndFlipMigratedFlag" ContinueOnError="false">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>requiresMigration</Value>
              <Value>False</Value>
              <Action>SkipThisValidationTechnicalProfile</Action>
            </Precondition>
          </Preconditions>
        </ValidationTechnicalProfile>

        <!-- Initiate a normal logon against Azure AD B2C -->
        <ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
      </ValidationTechnicalProfiles>
    </TechnicalProfile>
1
Can you provide snippets of the technical profiles. ROPC should allow you now to call a REST API before the ROPC technical profile from the user journey. This was an enhancement to enable seamless account migration to work with ROPC flows.Jas Suri - MSFT
@JasSuri I updated the code fragments for SelfAsserted as I was not able to upload the xml for ROPC with Validation Technical Profile, let me know if you need that as well,Sudhakar Betha
@JasSuri I uploaded both xmls fragments using OpenIdConnect and SelfAsserted , let me know if there is anything I need to change to get , ROPC SignIn->RestAPIValidate->AADWrite->token Thanks in advanceSudhakar Betha
@SudhakarBetha were you able to fix this issue? I have the same requirement for a project, tried everything but still getting erros when calling the endpointuser1862876

1 Answers

0
votes

Since its an ROPC policy, it cannot contain any selfasserted flows. What you need to do is create a journey like this:

Orchestration steps:

Step 1. Read user account using Email in B2C, output extension_requiresMigration

Step 2. If extension_requiresMigration = True -> Call REST API to send credentials to it. Return an error if the password is bad.

Step 3. If REST API said credentials are good -> Write user password to B2C account

Step 4. Run ROPC Technical profile (login-noninteractive)

Step 5. Read any other information from account in AAD B2C

Step 6. Issue a token