如何修改Azure AD B2C用户名登录自定义策略以支持邮箱登录
问题根因
该现象由登录标识存储位置和匹配逻辑不匹配导致:
- 你引用的用户名注册登录示例策略,默认仅将用户名以
signInNames.userName类型存入用户身份集合,注册时用于验证的邮箱不会写入可用于登录的身份条目 - Azure AD B2C默认邮箱登录逻辑仅匹配
signInNames.emailAddress类型的身份记录,无法识别仅绑定了用户名登录标识的账号 - 原示例的登录校验逻辑仅检索用户名类型的登录标识,不会匹配邮箱条目,因此不支持邮箱输入登录
配置修改方案
仅需两处核心修改即可实现用户名+注册邮箱双登录模式:
- 注册流程持久化用户数据时,将验证通过的邮箱额外写入
signInNames.emailAddress身份条目,为账号绑定两个可登录标识 - 登录流程的校验逻辑调整为自动识别用户输入内容类型,同时匹配用户名、邮箱两类登录标识
1. 注册流程持久化配置修改
打开策略扩展文件TrustFrameworkExtensions.xml,找到ID为AAD-UserWriteUsingLogonName的技术配置文件,在<PersistedClaims>节点下新增邮箱标识写入规则:
<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> <PersistedClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true"/> <!-- 新增以下规则:将注册验证通过的邮箱写入可登录身份集合 --> <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true"/> <!-- 原有其他持久化声明(displayName、password、givenName、surname等)保持不变,不要删除 --> </PersistedClaims> <OutputClaims> <!-- 原有输出声明保持不变 --> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common"/> </TechnicalProfile>
2. 登录流程校验逻辑修改
在同个TrustFrameworkExtensions.xml文件中,先新增邮箱格式判断的声明转换,再调整登录页的校验逻辑:
<!-- 新增:判断用户输入是否为邮箱格式的声明转换 --> <ClaimsTransformation Id="DetectSigninIdentifierType" TransformationMethod="IsEmail"> <InputClaims> <InputClaim ClaimTypeReferenceId="signInName" TransformationClaimType="inputClaim"/> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="isEmailInput" TransformationClaimType="outputClaim"/> </OutputClaims> </ClaimsTransformation> <!-- 修改原有用户名登录自断言配置 --> <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="setting.operatingMode">Username</Item> <Item Key="ContentDefinitionReferenceId">api.localaccountsignin</Item> <Item Key="setting.forgotPasswordLinkLocation">footer</Item> <!-- 修改登录提示文案,告知用户支持用户名/邮箱两种输入 --> <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">输入的用户名或邮箱不存在,请检查后重试</Item> <Item Key="UserMessageIfInvalidPassword">密码错误,请重试</Item> </Metadata> <InputClaimsTransformations> <!-- 登录校验前先判断输入类型 --> <InputClaimsTransformation ReferenceId="DetectSigninIdentifierType"/> </InputClaimsTransformations> <OutputClaims> <OutputClaim ClaimTypeReferenceId="signInName" Required="true"/> <OutputClaim ClaimTypeReferenceId="password" Required="true"/> <OutputClaim ClaimTypeReferenceId="rememberMe" DefaultValue="false" AlwaysUseDefaultValue="true"/> <OutputClaim ClaimTypeReferenceId="isEmailInput" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserReadBySigninIdentifier"/> <ValidationTechnicalProfile ReferenceId="login-NonInteractive"/> </ValidationTechnicalProfiles> <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD"/> </TechnicalProfile> <!-- 新增:自动匹配用户名/邮箱的用户读取配置 --> <TechnicalProfile Id="AAD-UserReadBySigninIdentifier"> <Metadata> <Item Key="Operation">Read</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> </Metadata> <InputClaims> <!-- 输入为邮箱时匹配email标识,否则匹配用户名标识 --> <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.emailAddress" Required="true" PreconditionType="ClaimEquals" PreconditionClaim="isEmailInput=True"/> <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true" PreconditionType="ClaimEquals" PreconditionClaim="isEmailInput=False"/> </InputClaims> <OutputClaims> <!-- 原有输出声明保持不变,比如objectId、displayName、signInName、email等 --> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common"/> </TechnicalProfile>
注意事项
- 代码中所有占位的客户端ID、租户ID等配置,请替换为你环境中实际的部署值,敏感信息自行替换即可
- 新注册用户会自动绑定用户名、邮箱双登录标识,直接支持两种方式登录
- 策略上线前创建的存量账号,需要通过Graph API补写
signInNames.emailAddress属性后,才能使用邮箱登录 - 配置上传后先使用测试账号验证:分别用用户名+密码、邮箱+密码尝试登录,确认两类方式都可正常鉴权
内容的提问来源于stack exchange,提问作者user17943200
相关产品推荐
相关产品推荐

