As i understand from documentation, Azure AD B2C creates a new local account for every user that comes from a social login such as GMail/Facebook while signin first time (Correct me, if i'm wrong). However i want to intercept this and link the user to an already existing (user's own) local account without creating a new local account, through custom policies.
The Wingtip sample contains an example of this flow.
See the "B2C_1A_link" relying party file and the "Link" user journey for reference.
Note this user journey prompts the end user to log in with a local account before they log in with the social account.
A detailed sample is given here.
Updating "user identities" will link the social account with the local account.
This can be achieved by having a user journey similar to the below.
<UserJourney Id="AccountLinkage">
<PreserveOriginalAssertion>false</PreserveOriginalAssertion>
<OrchestrationSteps>
<!-- Demo: The following orchestration step is always executed.
Asks user to sign-in with local account (only)-->
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
<!-- Demo: Sign-in with local account-->
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Demo: After user is sign-in, it reads the user, by user object ID,
from the Azure AD identity store. An error is raised if the user does not exist. -->
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Demo: After user is sign-in, and we have the user object ID.
Now, ask the user to re-sign-in, but this time with
one of the social account. This orchestration step, displays the sign-in with social
account buttons.
Note, You may want to add additional social accounts here-->
<OrchestrationStep Order="4" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
<ClaimsProviderSelections>
**<ClaimsProviderSelection TargetClaimsExchangeId="GoogleExchange" />
<ClaimsProviderSelection TargetClaimsExchangeId="AmazonAccountExchange" />**
</ClaimsProviderSelections>
</OrchestrationStep>
<!-- Demo: Run the sign-in with social account, based on user choice (from previous step)
Note, You may want to add additional social accounts here -->
<OrchestrationStep Order="5" Type="ClaimsExchange">
<ClaimsExchanges>
**<ClaimsExchange Id="GoogleExchange" TechnicalProfileReferenceId="Google-OAUTH" />
<ClaimsExchange Id="AmazonAccountExchange" TechnicalProfileReferenceId="AmazonAccount-OAuth2" />**
</ClaimsExchanges>
</OrchestrationStep>
<!-- Demo: Updates the social account for a user, identified by the object
identifier for the user, in the Azure AD identity store.
An error is raised if the user does not exist. -->
<OrchestrationStep Order="6" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AAD-UserWriteUsingAlternativeSecurityId-ThrowIfNotExists" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId-ThrowIfNotExists" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Demo: Re-reads the user, by user object Id, from the Azure Active Directory.
An error is raised if the user does not exist. -->
<OrchestrationStep Order="7" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectIdAfter" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Demo: Issues a JWT token to the relying party. -->
<OrchestrationStep Order="8" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
</UserJourney>
Then create a 'LinkExternalAccount.xml' policy similar to the below.
<RelyingParty>
<!-- Demo: This relying party policy executes the `AccountLinkage` user journey.
Please see the B2C_1A_Link_TrustFrameworkExtensions policy for more details -->
<DefaultUserJourney ReferenceId="AccountLinkage" />
<TechnicalProfile Id="PolicyProfile">
<DisplayName>PolicyProfile</DisplayName>
<Protocol Name="OpenIdConnect" />
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
<OutputClaim ClaimTypeReferenceId="identityProvider" />
</OutputClaims>
<SubjectNamingInfo ClaimType="sub" />
</TechnicalProfile>
Once we run our 'Linkexternalaccount.xml' it will redirect to our local account login and after successful login, it will ask for IDP selection and based on user selection 'User identities' attribute will be updated. We can check the same by querying against the user. A sample user identity looks like below,
**"userIdentities": [
{
"issuer": "google.com",
"issuerUserId": "MTA5MjA5ODQwNzAyNjc3NTEzMzM5"
}**
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With