【问题标题】:Can Azure-AD B2C use a mobile telephone number as a username?Azure-AD B2C 可以使用手机号码作为用户名吗?
【发布时间】:2019-05-28 01:36:04
【问题描述】:

我们有一个移动应用程序和网站。我们想使用 Azure AD-B2C 进行身份验证。我们不会允许任何第三方身份验证,而是仅在单独的域中使用 Azure AD。

我们更愿意使用用户的电话号码。我的研究表明,此功能是 requested,但目前不存在。

是否有任何解决方法,或者是否已实现此功能但我错过了?

【问题讨论】:

  • 嗨,布莱恩。您可以使用任何内容作为本地帐户的登录名,但您可能必须为此使用自定义策略。您要在注册使用之前验证电话号码吗?
  • 克里斯,确切地说,我们想向手机号码发送一条短信,并让用户验证他们确实拥有手机。我会为那部分使用自定义策略吗?
  • 嗨 Bryan:是的,为此需要自定义策略,请参阅下面的示例策略。

标签: azure azure-active-directory azure-ad-b2c


【解决方案1】:

这可以实现为 a custom policy,来自 the SocialAndLocalAccountsWithMfa starter pack,其中最终用户的电话号码存储为登录名,并进行了以下更改。

1) 创建名为 PhoneVerified 且类型为 Booleana custom attribute,以表示最终用户的电话号码是否已经过验证。

2) 在the TrustFrameworkBase.xml file 中,将以下声明类型添加到声明架构中:

我。 phone 声明类型,表示最终用户的电话号码是如何输入的。 E.164 是此声明类型的必需格式:

<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>

二。 signInNames.phoneNumber 声明类型,表示最终用户电话号码的保存方式:

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

三。 extension_PhoneVerified 声明类型,表示最终用户的电话号码是否已经过验证:

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

3) 在 TrustFrameworkBase.xml 文件中,将 LocalAccountSignUpWithLogonPhone 技术配置文件添加到 Local Account 声明提供程序和 AAD- Azure Active Directory 声明提供商的 UserWriteUsingLogonPhone 技术配置文件,用于使用电话号码注册新的最终用户:

<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>

最终用户的电话号码保存为 phoneNumber 类型的登录名,并且将最终用户的电话号码是否经过验证设置为 false

4) 在 TrustFrameworkBase.xml 文件中,将 SelfAsserted-LocalAccountSignin-Phone 技术配置文件添加到 Local Account 声明提供程序,用于使用电话号码登录现有的最终用户:

<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>

setting.operatingMode 设置设置为 Username,因此登录标识符字段没有电子邮件地址所需的格式。

5) 在 TrustFrameworkBase.xml 文件中,将 AAD-UserReadForPhoneUsingObjectId 技术添加到 Azure Active Directory 声明提供程序,以获取最终用户的对象,包括电话配置文件:

<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) 在 TrustFrameworkBase.xml 文件中,将 PhoneFactor-Verify 技术配置文件添加到 Phone Factor 声明提供程序,以验证最终用户的电话号码:

<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) 在 TrustFrameworkBase.xml 文件中,将 UserWritePhoneVerifiedUsingObjectId 技术配置文件添加到 Azure Active Directory 声明提供程序,用于设置是否最终用户的电话号码已被验证为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>

注意:必须在 TrustFrameworkBase.xml 文件中添加其他技术配置文件,以允许现有最终用户使用电话号码重置其当前密码,但这有留给读者作为练习。

8) 在 TrustFrameworkBase.xml 文件中,添加 SignUpOrSignInForPhone 用户旅程,允许新最终用户使用电话号码或现有终端注册-user 使用电话号码登录,然后验证最终用户的电话号码。

<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) 创建名为 SignUpOrSignInForPhone.xml(或类似名称)的 a relying party file 并引用 SignUpOrSignInForPhone 用户旅程:

<?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>

输出给依赖方的令牌声明包括:

我。 phone_number 声明,代表最终用户的电话号码。

二。 phone_number_verified 声明表示最终用户的电话号码是否已经过验证。

【讨论】:

  • 克里斯,非常感谢你。太棒了!!
  • 嗨,克里斯,您能帮我为上述实施添加自定义密码重置策略吗(手机号登录注册)
  • 克里斯,这引用了似乎不存在的“AAD-UserWritePhoneVerifiedUsingObjectId”。这应该是“AAD-UserWritePhoneNumberUsingObjectId”吗?
  • 嗨,克里斯,帮了大忙。要确认是否必须添加额外的验证来检查移动电话号码?据我所知,这适用于任何电话号码,那么验证是否会尝试发送到非手机号码?
  • 仅供参考:Microsoft 建议不要修改 TrustFrameworkBase.xml。您应该始终在基础之上创建一个扩展文件。
【解决方案2】:
【解决方案3】:

我可以使用手机号码在内置登录或注册策略中注册为本地用户名。流程如下:

结果是:

或者您也可以像 Chris Padgett 所说的那样使用自定义策略来实现。

【讨论】:

  • 我们还希望能够通过向用户发送文本并让他们采取一些操作(例如点击 URL)来验证电话号码。自定义政策可以做到这一点吗?
  • @BryanSchmiedeler,您可以在内置策略中启用 MFA。详情可参考here
  • 太棒了。现在,如果我想添加重置密码策略怎么办。您能否为此与我分享步骤和自定义政策。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 2018-04-27
  • 2022-01-09
  • 2018-01-16
  • 2021-03-03
  • 1970-01-01
相关资源
最近更新 更多