Can Azure-AD B2C use a mobile telephone number as

2020-03-03 06:36发布

We have a mobile app and website. We would like to use Azure AD-B2C for authentication. We are not going to allow any third party authentication, but instead just use Azure AD in a separate domain.

We would prefer to use the user's telephone number. My research suggests that this feature is requested, but does not exist at this time.

Are there any workarounds for this, or has this feature been implemented and I missed it?

3条回答
一夜七次
2楼-- · 2020-03-03 07:05

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.

查看更多
手持菜刀,她持情操
3楼-- · 2020-03-03 07:08

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.

查看更多
登录 后发表回答