Changing the federation button into a link in Azure AD B2C

Rory Braybrook
The new control plane
3 min readJan 4, 2024
Image showing chain links
Link-dynamic-gradient.png from Wikimedia

This post refers to this sample, in particular, Phone_Email_Base.xml.

When you run the user journey for phone and email, you get:

Image showing “Change Phone Number” as a link

Notice the link at the bottom! It would typically be a button.

Looking at the code:

<UserJourney Id="SignUpOrSignInWithPhoneOrEmail">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="signuporsignin-phone-email">
<ClaimsProviderSelections>
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninPhoneEmailExchange" />
<ClaimsProviderSelection TargetClaimsExchangeId="SignUpWithEmail" />
<ClaimsProviderSelection TargetClaimsExchangeId="SignUpWithPhone" />
<ClaimsProviderSelection TargetClaimsExchangeId="ChangePhoneNumber" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninPhoneEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Phone-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>isLocalAccountSignIn</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>objectId</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SignUpWithPhone" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonPhoneNumber" />
<ClaimsExchange Id="SignUpWithEmail" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
<ClaimsExchange Id="ChangePhoneNumber" TechnicalProfileReferenceId="PhoneInputPage-ChangePhoneNumberClaimsProviderSelection" />
</ClaimsExchanges>
</OrchestrationStep>

So “ChangePhoneNumber” is a ClaimsProviderSelection (i.e. a “federation” button).

How, then, does it become a link?

“PhoneInputPage-ChangePhoneNumberClaimsProviderSelection” looks like:

<TechnicalProfile Id="PhoneInputPage-ChangePhoneNumberClaimsProviderSelection">
<DisplayName>Change Phone Number</DisplayName>
<Metadata>
<Item Key="ClaimsProviderSelectionDisplayType">TextLink</Item>
</Metadata>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="isChangePhoneNumber" DefaultValue="true" AlwaysUseDefaultValue="true"/>
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="PhoneInput-ChangePhoneNumber-Common"/>
</TechnicalProfile>

So, it’s setting a flag used later in the user journey. This is the same technique used in the embedded password reset.

Notice the metadata item “TextLink”.

This is an undocumented feature; the only reference when you Google it is to the “PhoneOrEmail” sample!

Notice also the ContentDefinition for the user journey.

<ContentDefinition Id="signuporsignin-phone-email">
<LoadUri>~/tenant/templates/AzureBlue/unified.cshtml</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:2.1.1</DataUri>
<Metadata>
<Item Key="DisplayName">Signin and Signup using phone or email</Item>
<Item Key="setting.bottomUnderFormClaimsProviderSelections">ChangePhoneNumber</Item>
</Metadata>
<LocalizedResourcesReferences MergeBehavior="Prepend">
<LocalizedResourcesReference Language="en" LocalizedResourcesReferenceId="signuporsignin-phone-email.en"/>
</LocalizedResourcesReferences>
</ContentDefinition>

The metadata item is:

Key=”setting.bottomUnderFormClaimsProviderSelections” ChangePhoneNumber

This is also undocumented.

“ChangePhoneNumber” is the ID of the ClaimsExchange that calls the “PhoneInputPage-ChangePhoneNumberClaimsProviderSelection” technical profile.

It would be nice to include some more detail, but since it’s all undocumented, it’s hard 😄

Also, notice this code:

<LocalizedString ElementType="UxElement" StringId="initial_intro">Please verify your country code and phone number</LocalizedString>
<!-- The following elements will display a message and two links at the bottom of the signin page.
For policies that you intend to show to users in the United States, we suggest displaying the following text. Replace the content of the disclaimer_link_X_url elements with links to your organization's privacy statement and terms and conditions.
Remove any of these lines if you do not wish to display them. -->
<LocalizedString ElementType="UxElement" StringId="disclaimer_msg_intro">By providing your phone number, you consent to receiving a one-time passcode sent by text message to help you sign into {insert your application name}. Standard messsage and data rates may apply.</LocalizedString>
<LocalizedString ElementType="UxElement" StringId="disclaimer_link_1_text">Privacy Statement</LocalizedString>
<LocalizedString ElementType="UxElement" StringId="disclaimer_link_1_url">{insert your privacy statement URL}</LocalizedString>
<LocalizedString ElementType="UxElement" StringId="disclaimer_link_2_text">Terms and Conditions</LocalizedString>
<LocalizedString ElementType="UxElement" StringId="disclaimer_link_2_url">{insert your terms and conditions URL}</LocalizedString>

So, you can have text and a hyperlink!

But only two of them.

All good!

--

--

Rory Braybrook
The new control plane

NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: https://bit.ly/2XU4yvJ Presentations: http://bit.ly/334ZPt5