You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义邮件验证导致Azure AD B2C两步式自定义注册策略失效

问题描述

我搭建了一个两步式自定义注册流程:第一步验证邮箱,第二步设置新密码,原本运行正常。之后我配置了自定义邮件验证器(用DisplayControl实现)来发送自定义内容的验证码,验证码发送功能正常,但添加配置后流程出现异常:第一步无法输出email声明,导致第二步中依赖email的CreateReadonlyEmailClaim声明转换失败。移除第一步TechnicalProfile中的<DisplayClaims>部分后流程恢复正常,请问遗漏了什么配置?

相关配置代码:

<ClaimsTransformation Id="CreateReadonlyEmailClaim" TransformationMethod="FormatStringClaim">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="inputClaim" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="stringFormat" DataType="string" Value="{0}" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="readonlyEmail" TransformationClaimType="outputClaim" />
  </OutputClaims>
</ClaimsTransformation>

<!-- 2 step partner sign-up -->
<TechnicalProfile Id="PartnerSignUpVerifyEmailPage">
    <DisplayName>Local Email Verification</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.signUpVerifyEmailPage</Item>
        <Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">A user with this email address already exists.</Item>
    </Metadata>
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="email" />
    </InputClaims>

    <!-- 添加上这段后流程异常 -->
    <DisplayClaims>
        <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
    </DisplayClaims>

    <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
    </OutputClaims>
    <ValidationTechnicalProfiles>
        <!-- 验证邮箱未被注册 -->
        <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress-RaiseIfExists" />
    </ValidationTechnicalProfiles>
    <IncludeTechnicalProfile ReferenceId="AAD-Common" />
    <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>

<TechnicalProfile Id="PartnerSignUpSetNewPasswordPage">
    <DisplayName>Local Email 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.signUpSetNewPasswordPage</Item>
        <Item Key="EnforceEmailVerification">False</Item>
    </Metadata>
    <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
    </InputClaimsTransformations>
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="readOnlyEmail" />
    </InputClaims>
    <OutputClaims>
        <!--OutputClaim ClaimTypeReferenceId="objectId" />
        <OutputClaim ClaimTypeReferenceId="readOnlyEmail" /-->
        <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
        <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
        <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
        <OutputClaim ClaimTypeReferenceId="newUser" />
    </OutputClaims>
    <ValidationTechnicalProfiles>
        <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
    </ValidationTechnicalProfiles>
    <IncludeTechnicalProfile ReferenceId="AAD-Common" />
    <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
解决方案

问题出在使用自定义邮件验证DisplayControl时,未正确配置声明的传递逻辑,导致第一步的email声明无法进入会话传递到第二步。以下是具体修复步骤:

1. 给第一步的TechnicalProfile添加声明解析元数据

在PartnerSignUpVerifyEmailPage的<Metadata>节点中添加以下项,确保系统能正确处理DisplayControl的输出声明:

<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>

2. 确保emailVerificationControl的声明绑定正确

检查你的emailVerificationControl DisplayControl定义,必须包含输入输出的email声明绑定,确保用户输入/验证后的邮箱能被传递回TechnicalProfile:

<DisplayControl Id="emailVerificationControl" DisplayName="Email Verification">
  <!-- 接收从TechnicalProfile传入的初始邮箱 -->
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" />
  </InputClaims>
  <!-- 显示邮箱输入框和验证码输入框 -->
  <DisplayClaims>
    <DisplayClaim ClaimTypeReferenceId="email" Required="true" />
    <DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" Required="true" />
  </DisplayClaims>
  <!-- 输出验证后的邮箱声明,绑定到TechnicalProfile的email声明 -->
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="email" />
  </OutputClaims>
  <!-- 发送/验证验证码的动作配置 -->
  <Actions>
    <Action Id="SendCode">
      <ValidationClaimsExchange>
        <ValidationClaimsExchangeTechnicalProfile ReferenceId="SendVerificationCode" />
      </ValidationClaimsExchange>
    </Action>
    <Action Id="VerifyCode">
      <ValidationClaimsExchange>
        <ValidationClaimsExchangeTechnicalProfile ReferenceId="VerifyVerificationCode" />
      </ValidationClaimsExchange>
    </Action>
  </Actions>
</DisplayControl>

3. 调整第一步TechnicalProfile的OutputClaims配置

移除OutputClaim中的PartnerClaimType="Verified.Email",因为DisplayControl已经完成验证,直接输出原始email声明即可,确保会话中能保留该声明:

<OutputClaims>
  <OutputClaim ClaimTypeReferenceId="email" Required="true" />
</OutputClaims>

4. 确认会话管理保留email声明

确保第一步TechnicalProfile使用的SessionManagement(SM-AAD)配置中包含email声明的持久化,默认SM-AAD配置已处理基本声明的保存,若有自定义配置需检查是否遗漏email声明。

完成以上修改后,第一步验证完成后email声明会被正确保存到用户会话中,第二步的CreateReadonlyEmailClaim声明转换就能正常获取到邮箱输入,流程即可恢复正常。

内容的提问来源于stack exchange,提问作者fei0x

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:05:22