Can Azure-AD B2C use a mobile telephone number as a username? Can Azure-AD B2C use a mobile telephone number as a username? azure azure

Can Azure-AD B2C use a mobile telephone number as a username?


This can be implemented as a custom policy, from the SocialAndLocalAccountsWithMfa starter pack where the end-user's phone number is stored as a sign-in name, with the following changes.

1) Create a custom attribute called PhoneVerified of type Boolean to represent whether the end-user's phone number has been verified.

2) In the TrustFrameworkBase.xml file, add the following claim types to the claims schema:

i. The phone claim type to represent how the end-user's phone number is entered. E.164 is the required format of this claim type:

<ClaimType Id="phone">  <DisplayName>Phone Number</DisplayName>  <DataType>string</DataType>  <UserInputType>TextBox</UserInputType>  <Restriction>    <Pattern RegularExpression="^\+[0-9]{7,15}$" HelpText="Please enter a valid phone number." />  </Restriction></ClaimType>

ii. The signInNames.phoneNumber claim type to represent how the end-user's phone number is saved:

<ClaimType Id="signInNames.phoneNumber">  <DisplayName>Phone Number</DisplayName>  <DataType>string</DataType>  <UserInputType>TextBox</UserInputType></ClaimType>

iii. The extension_PhoneVerified claim type to represent whether the end-user's phone number has been verified:

<ClaimType Id="extension_PhoneVerified">  <DisplayName>Phone Number Verified</DisplayName>  <DataType>boolean</DataType></ClaimType>

3) In the TrustFrameworkBase.xml file, add the LocalAccountSignUpWithLogonPhone tehcnical profile to the Local Account claims provider and AAD-UserWriteUsingLogonPhone technical profile to the Azure Active Directory claims provider, for registering a new end-user with a phone number:

<TechnicalProfile Id="LocalAccountSignUpWithLogonPhone">  <DisplayName>Phone signup</DisplayName>  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />  <Metadata>    <Item Key="IpAddressClaimReferenceId">IpAddress</Item>    <Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>    <Item Key="language.button_continue">Create</Item>  </Metadata>  <CryptographicKeys>    <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />  </CryptographicKeys>  <OutputClaims>    <OutputClaim ClaimTypeReferenceId="objectId" />    <OutputClaim ClaimTypeReferenceId="phone" Required="true" />    <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />    <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />    <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />    <OutputClaim ClaimTypeReferenceId="authenticationSource" />    <OutputClaim ClaimTypeReferenceId="newUser" />    <!-- Optional claims, to be collected from the user -->    <OutputClaim ClaimTypeReferenceId="displayName" />    <OutputClaim ClaimTypeReferenceId="givenName" />    <OutputClaim ClaimTypeReferenceId="surname" />  </OutputClaims>  <ValidationTechnicalProfiles>    <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonPhone" />  </ValidationTechnicalProfiles>  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /></TechnicalProfile>
<TechnicalProfile Id="AAD-UserWriteUsingLogonPhone">  <Metadata>    <Item Key="Operation">Write</Item>    <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>  </Metadata>  <IncludeInSso>false</IncludeInSso>  <InputClaims>    <InputClaim ClaimTypeReferenceId="phone" PartnerClaimType="signInNames.phoneNumber" Required="true" />  </InputClaims>  <PersistedClaims>    <!-- Required claims -->    <PersistedClaim ClaimTypeReferenceId="phone" PartnerClaimType="signInNames.phoneNumber" />    <PersistedClaim ClaimTypeReferenceId="newPassword" PartnerClaimType="password"/>    <PersistedClaim ClaimTypeReferenceId="displayName" DefaultValue="unknown" />    <PersistedClaim ClaimTypeReferenceId="passwordPolicies" DefaultValue="DisablePasswordExpiration" />    <PersistedClaim ClaimTypeReferenceId="extension_PhoneVerified" DefaultValue="false" AlwaysUseDefaultValue="true" />    <!-- Optional claims. -->    <PersistedClaim ClaimTypeReferenceId="givenName" />    <PersistedClaim ClaimTypeReferenceId="surname" />  </PersistedClaims>  <OutputClaims>    <OutputClaim ClaimTypeReferenceId="objectId" />    <OutputClaim ClaimTypeReferenceId="newUser" PartnerClaimType="newClaimsPrincipalCreated" />    <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />    <OutputClaim ClaimTypeReferenceId="userPrincipalName" />    <OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber" />  </OutputClaims>  <IncludeTechnicalProfile ReferenceId="AAD-Common" />  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /></TechnicalProfile>

The end-user's phone number is saved as a sign-in name of type phoneNumber and whether the end-user's phone number has been verified is set to false.

4) In the TrustFrameworkBase.xml file, add a SelfAsserted-LocalAccountSignin-Phone technical profile to the Local Account claims provider, for logging in an existing end-user with a phone number:

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Phone">  <DisplayName>Local Account Signin</DisplayName>  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />  <Metadata>    <Item Key="SignUpTarget">SignUpWithLogonPhoneExchange</Item>    <Item Key="setting.operatingMode">Username</Item>    <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>  </Metadata>  <IncludeInSso>false</IncludeInSso>  <InputClaims>    <InputClaim ClaimTypeReferenceId="signInName" />  </InputClaims>  <OutputClaims>    <OutputClaim ClaimTypeReferenceId="signInName" Required="true" />    <OutputClaim ClaimTypeReferenceId="password" Required="true" />    <OutputClaim ClaimTypeReferenceId="objectId" />    <OutputClaim ClaimTypeReferenceId="authenticationSource" />  </OutputClaims>  <ValidationTechnicalProfiles>    <ValidationTechnicalProfile ReferenceId="login-NonInteractive" />  </ValidationTechnicalProfiles>  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /></TechnicalProfile>

The setting.operatingMode setting is set to Username so that the logon identifier field doesn't have the required format of an email address.

5) In the TrustFrameworkBase.xml file, add a AAD-UserReadForPhoneUsingObjectId technical to the Azure Active Directory claims provider, for getting the end-user's object including the phone profile:

<TechnicalProfile Id="AAD-UserReadForPhoneUsingObjectId">  <Metadata>    <Item Key="Operation">Read</Item>    <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>  </Metadata>  <IncludeInSso>false</IncludeInSso>  <InputClaims>    <InputClaim ClaimTypeReferenceId="objectId" Required="true" />  </InputClaims>  <OutputClaims>    <OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber" />    <OutputClaim ClaimTypeReferenceId="displayName" />    <OutputClaim ClaimTypeReferenceId="givenName" />    <OutputClaim ClaimTypeReferenceId="surname" />    <OutputClaim ClaimTypeReferenceId="extension_PhoneVerified" />  </OutputClaims>  <IncludeTechnicalProfile ReferenceId="AAD-Common" /></TechnicalProfile>

6) In the TrustFrameworkBase.xml file, add a PhoneFactor-Verify technical profile to the Phone Factor claims provider, for verifying the end-user's phone number:

<TechnicalProfile Id="PhoneFactor-Verify">  <DisplayName>PhoneFactor</DisplayName>  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />  <Metadata>    <Item Key="ContentDefinitionReferenceId">api.phonefactor</Item>    <Item Key="ManualPhoneNumberEntryAllowed">false</Item>  </Metadata>  <CryptographicKeys>    <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />  </CryptographicKeys>  <InputClaimsTransformations>    <InputClaimsTransformation ReferenceId="CreateUserIdForMFA" />  </InputClaimsTransformations>  <InputClaims>    <InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="userId" />    <InputClaim ClaimTypeReferenceId="signInNames.phoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" />  </InputClaims>  <OutputClaims>    <OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber" PartnerClaimType="Verified.strongAuthenticationPhoneNumber" />  </OutputClaims>  <UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" /></TechnicalProfile>

7) In the the TrustFrameworkBase.xml file, add an UserWritePhoneVerifiedUsingObjectId technical profile to the Azure Active Directory claims provider, for setting whether the end-user's phone number has been verified to true:

<TechnicalProfile Id="AAD-UserWritePhoneNumberUsingObjectId">  <Metadata>    <Item Key="Operation">Write</Item>    <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item>    <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>  </Metadata>  <IncludeInSso>false</IncludeInSso>  <InputClaims>    <InputClaim ClaimTypeReferenceId="objectId" Required="true" />  </InputClaims>  <PersistedClaims>    <PersistedClaim ClaimTypeReferenceId="objectId" />    <PersistedClaim ClaimTypeReferenceId="extension_PhoneVerified" DefaultValue="true" AlwaysUseDefaultValue="true" />  </PersistedClaims>  <IncludeTechnicalProfile ReferenceId="AAD-Common" /></TechnicalProfile>

Note: Additional technical profiles must be added in the TrustFrameworkBase.xml file to allow an existing end-user to reset their current password using a phone number but this has been left as an exercise for the reader.

8) In the TrustFrameworkBase.xml file, add a SignUpOrSignInForPhone user journey, which allows either a new end-user to register with a phone number or an existing end-user to log in with a phone number and then verifies the end-user's phone number.

<UserJourney Id="SignUpOrSignInForPhone">  <OrchestrationSteps>    <!-- Display the sign-up or sign-in interaction so an existing end-user can sign in with a phone number -->          <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">      <ClaimsProviderSelections>        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninPhoneExchange" />      </ClaimsProviderSelections>      <ClaimsExchanges>        <ClaimsExchange Id="LocalAccountSigninPhoneExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Phone" />      </ClaimsExchanges>    </OrchestrationStep>    <!-- A new end-user has selected to sign up with a phone number -->    <OrchestrationStep Order="2" Type="ClaimsExchange">      <Preconditions>        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">          <Value>objectId</Value>          <Action>SkipThisOrchestrationStep</Action>        </Precondition>      </Preconditions>      <ClaimsExchanges>        <ClaimsExchange Id="SignUpWithLogonPhoneExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonPhone" />      </ClaimsExchanges>    </OrchestrationStep>    <!-- Read the user object -->    <OrchestrationStep Order="3" Type="ClaimsExchange">      <ClaimsExchanges>        <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadForPhoneUsingObjectId" />      </ClaimsExchanges>    </OrchestrationStep>    <!-- If the end-user's phone number hasn't been verified, then verify it during sign-up or following the first sign-in with an unverified phone number -->    <OrchestrationStep Order="4" Type="ClaimsExchange">      <Preconditions>        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">          <Value>extension_PhoneVerified</Value>          <Value>True</Value>          <Action>SkipThisOrchestrationStep</Action>        </Precondition>        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">          <Value>isActiveMFASession</Value>          <Action>SkipThisOrchestrationStep</Action>        </Precondition>      </Preconditions>      <ClaimsExchanges>        <ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-Verify" />      </ClaimsExchanges>    </OrchestrationStep>    <!-- Set whether the end-user's phone number has been verified to true -->    <OrchestrationStep Order="5" Type="ClaimsExchange">      <Preconditions>        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">          <Value>extension_PhoneVerified</Value>          <Value>True</Value>          <Action>SkipThisOrchestrationStep</Action>        </Precondition>        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">          <Value>isActiveMFASession</Value>          <Action>SkipThisOrchestrationStep</Action>        </Precondition>      </Preconditions>      <ClaimsExchanges>        <ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneVerifiedUsingObjectId" />      </ClaimsExchanges>    </OrchestrationStep>    <OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />  </OrchestrationSteps></UserJourney>

9) Create a relying party file called SignUpOrSignInForPhone.xml (or similar) and reference the SignUpOrSignInForPhone user journey:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><TrustFrameworkPolicy    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:xsd="http://www.w3.org/2001/XMLSchema"    xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06"    PolicySchemaVersion="0.3.0.0"    TenantId="yourtenant.onmicrosoft.com"    PolicyId="B2C_1A_signup_signin_phone"    PublicPolicyUri="http://yourtenant.onmicrosoft.com/B2C_1A_signup_signin_phone">  <BasePolicy>    <TenantId>yourtenant.onmicrosoft.com</TenantId>    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>  </BasePolicy>  <RelyingParty>    <DefaultUserJourney ReferenceId="SignUpOrSignInForPhone" />    <TechnicalProfile Id="PolicyProfile">      <DisplayName>PolicyProfile</DisplayName>      <Protocol Name="OpenIdConnect" />      <OutputClaims>        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />        <OutputClaim ClaimTypeReferenceId="displayName" />        <OutputClaim ClaimTypeReferenceId="givenName" />        <OutputClaim ClaimTypeReferenceId="surname" />        <OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber" PartnerClaimType="phone_number" />        <OutputClaim ClaimTypeReferenceId="extension_PhoneNumber" PartnerClaimType="phone_number_verified" />      </OutputClaims>      <SubjectNamingInfo ClaimType="sub" />    </TechnicalProfile>  </RelyingParty></TrustFrameworkPolicy>

The token claims that are output to a relying party include:

i. The phone_number claim that represents the end-user's phone number.

ii. The phone_number_verified claims that represents whether the end-user's phone number has been verified.


I could use a mobile telephone number to sign up as the username for the local in the built-in sign-in or sign-up policy. The process like the following:

enter image description here

And the result is:

enter image description here

Or you could also use the custom policy to make this just like Chris Padgett said.