启用用户名登录流程后,防止 Azure B2C 用户使用电子邮件地址登录

Prevent Azure B2C users from logging in with an email address when the username login flow is enabled

我在 Azure AD B2C 中设置了一些自定义策略,其中之一是用户使用其用户名登录的流程。我使用了以下 github code 作为参考。我的问题是以前使用电子邮件地址设置的用户也可以使用他们的电子邮件地址作为用户名通过用户名流登录。我想阻止这种情况。

这是我的前两个 UserJourney 步骤:

<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
  <ClaimsProviderSelections>
    <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
  </ClaimsProviderSelections>
  <ClaimsExchanges>
    <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Username" />
  </ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
  <Preconditions>
    <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
      <Value>objectId</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <ClaimsExchanges>
    <ClaimsExchange Id="SignUpWithLogonUsernameExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonName" />
  </ClaimsExchanges>
</OrchestrationStep>

SelfAsserted-LocalAccountSignin-Username 的技术资料。

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Username">
  <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">SignUpWithLogonUsernameExchange</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>

SignUpTarget 元数据引用了 SignUpWithLogonUsernameExchange,它具有 LocalAccountSignUpWithLogonName 的技术配置文件,如 UserJourney.

的第二步所示
<TechnicalProfile Id="LocalAccountSignUpWithLogonName">
  <DisplayName>Username 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="LocalAccountType">Username</Item>
    <Item Key="LocalAccountProfile">true</Item>
    <Item Key="language.button_continue">Create</Item>
  </Metadata>
  <CryptographicKeys>
    <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
  </CryptographicKeys>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="objectId" />
    <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" 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-UserWriteUsingLogonName" />
  </ValidationTechnicalProfiles>
  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>

以及 AAD-UserWriteUsingLogonName 验证技术资料。

<TechnicalProfile Id="AAD-UserWriteUsingLogonName">
  <Metadata>
    <Item Key="Operation">Write</Item>
    <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
  </Metadata>
  <IncludeInSso>false</IncludeInSso>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true" />
  </InputClaims>
  <PersistedClaims>
    <!-- Required claims -->
    <PersistedClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" />
    <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="strongAuthenticationEmailAddress" />
    <PersistedClaim ClaimTypeReferenceId="newPassword" PartnerClaimType="password" />
    <PersistedClaim ClaimTypeReferenceId="displayName" DefaultValue="unknown" />
    <PersistedClaim ClaimTypeReferenceId="passwordPolicies" DefaultValue="DisablePasswordExpiration" />
    <!-- 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.emailAddress" />
  </OutputClaims>
  <IncludeTechnicalProfile ReferenceId="AAD-Common" />
  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>

以下是每个用户的身份:

用户 1

"identities":[
  {
     "signInType":"emailAddress",
     "issuer":"{tenant}.onmicrosoft.com",
     "issuerAssignedId":"userOne@yahoo.com"
  },
  {
     "signInType":"userPrincipalName",
     "issuer":"{tenant}.onmicrosoft.com",
     "issuerAssignedId":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX@{tenant}.onmicrosoft.com"
  }
]

用户 2:

"identities":[
  {
     "signInType":"userName",
     "issuer":"{tenant}.onmicrosoft.com",
     "issuerAssignedId":"userTwo"
  },
  {
     "signInType":"userPrincipalName",
     "issuer":"{tenant}.onmicrosoft.com",
     "issuerAssignedId":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX@{tenant}.onmicrosoft.com"
  }
]

感谢任何帮助。

在登录技术配置文件中,添加验证技术配置文件以读取帐户,使用signInNames.username。如果用户不存在,则将其元数据配置为抛出错误。在登录非交互式验证技术配置文件之前插入此内容。

解决方案:

<TechnicalProfile Id="AAD-ReadUsingUsername">
   <Metadata>
      <Item Key="Operation">Read</Item>
      <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
   </Metadata>
   <InputClaims>
      <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true" />
   </InputClaims>
   <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="objectId" />
   </OutputClaims>
</TechnicalProfile>
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Username">
...snip...
<ValidationTechnicalProfiles>
   <ValidationTechnicalProfile ReferenceId="AAD-ReadUsingUsername" />
   <ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
</ValidationTechnicalProfiles>
...snip...

参考文献:
Understand the starter pack
Azure AD R/W Technical Profile