3

First orchestration step is login- taking email output claim Second step is email verify- I want to populate email from login and verify with email OTP.

Problem- If email populated, verify button does not come. If verify button comes, email not populated.

4

2 回答 2

2

我能够通过在 DisplayClaim 中使用 DisplayControl 而不是在 OutputClaim 中使用 Verified.Email 来解决这个用例。

首先在您的 BuildingBlocks、ClaimsSchema 中定义这两个属性:

<BuildingBlocks>
  <ClaimsSchema>

    <ClaimType Id="readOnlyEmail">
      <DisplayName>Email</DisplayName>
      <DataType>string</DataType>
      <UserInputType>Readonly</UserInputType>
    </ClaimType>
    <ClaimType Id="verificationCode">
      <DisplayName>Secondary Verification Code</DisplayName>
      <DataType>string</DataType>
      <UserHelpText>Enter your email verification code</UserHelpText>
      <UserInputType>TextBox</UserInputType>
    </ClaimType>

    <!-- Other claims you have defined -->

  </ClaimsSchema>
</BuildingBlocks>

我们将把 email 属性复制到 readOnlyEmail 属性中,以便我们可以在屏幕上显示它,并且在验证电子邮件一次性密码 (OTP) 时使用 verifyCode 属性。在这里坚持我。

在 BuildingBlocks 中定义一个 ClaimsTransformation,ClaimsTransformation 通过电子邮件复制到 readOnlyEmail。

<BuildingBlocks>

  <!-- ClaimsSchema -->

  <ClaimsTransformations>
    <ClaimsTransformation Id="CopyEmailAddress" TransformationMethod="CopyClaim">
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="inputClaim"/>
      </InputClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="readOnlyEmail" TransformationClaimType="outputClaim"/>
      </OutputClaims>
    </ClaimsTransformation>
  </ClaimsTransformations>

  <!-- ContentDefinitions, DisplayControls, etc. -->

</BuildingBlocks>

修改 api.selfasserted 的 ContentDefinition 中的 DataUri 元素,使其成为版本 2.0.0 并包含“contract”标签。您必须这样做才能允许 DisplayClaims 工作。

api.selfasserted ContentDefinition 现在应该如下所示:

<BuildingBlocks>

  <!-- ClaimsSchema, ClaimsTransformations -->

  <ContentDefinitions>
    <ContentDefinition Id="api.selfasserted">
      <LoadUri>~/tenant/templates/AzureBlue/selfAsserted.cshtml</LoadUri>
      <RecoveryUri>~/common/default_page_error.html</RecoveryUri>
      <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.0.0</DataUri>
      <Metadata>
        <Item Key="DisplayName">Collect information from user page</Item>
      </Metadata>
    </ContentDefinition>
  </ContentDefinitions>

  <!-- DisplayControls, etc. -->

</BuildingBlocks>

这里唯一的变化是 ContentDefinition 中的 DataUri 元素。请注意,我们更新了它以包含“合同”一词,它的版本现在是 2.0.0。

然后在 BuildingBlocks 中定义一个 DisplayControl,使用我们的 readOnlyEmail 和 verficationCode ClaimTypes 的 DisplayControls:

<BuildingBlocks>

  <!-- ClaimsSchema, ClaimsTransformations, ContentDefinitions, etc -->

  <DisplayControls>
    <DisplayControl Id="emailVerificationControl" UserInterfaceControlType="VerificationControl">
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="readOnlyEmail" />
      </InputClaims>
      <DisplayClaims>
        <DisplayClaim ClaimTypeReferenceId="readOnlyEmail" />
        <DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" />
      </DisplayClaims>
      <Actions>
        <Action Id="SendCode">
          <ValidationClaimsExchange>
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AadSspr-SendCode" />
          </ValidationClaimsExchange>
        </Action>
        <Action Id="VerifyCode">
          <ValidationClaimsExchange>
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AadSspr-VerifyCode" />
          </ValidationClaimsExchange>
        </Action>
      </Actions>
    </DisplayControl>
  </DisplayControls>

</BuildingBlocks>

请注意,这里我们显示的是 readOnlyEmail,第二个 DisplayClaim for verificationCode 用于在将 OTP 发送到您的电子邮件后收集它。

还要注意指向我们尚未定义的 TechnicalProfiles 的 Actions。它们对应于屏幕上的按钮,将发送电子邮件并验证代码。接下来让我们定义这些。您可以将它们放在您想要的任何 ClaimsProvider 中:

<TechnicalProfile Id="AadSspr-SendCode">
  <DisplayName>Send Code</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AadSsprProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="Operation">SendCode</Item>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="readOnlyEmail" PartnerClaimType="emailAddress"/>
  </InputClaims>
</TechnicalProfile>

<TechnicalProfile Id="AadSspr-VerifyCode">
  <DisplayName>Verify Code</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AadSsprProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="Operation">VerifyCode</Item>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="verificationCode" PartnerClaimType="verificationCode" />
    <InputClaim ClaimTypeReferenceId="readOnlyEmail" PartnerClaimType="emailAddress"/>
  </InputClaims>
</TechnicalProfile>

这些 TechnicalProfiles 正在利用 AadSsprProtocolProvider 来发送和验证代码。MS在这里有很好的文档:https ://docs.microsoft.com/en-us/azure/active-directory-b2c/aad-sspr-technical-profile

差不多好了。现在让我们创建一个 SelfAssertedAttributeProvider TechnicalProfile 以利用我们新的 DisplayClaim 来进行内联验证。

在您想要的任何 ClaimsProvider 中创建此 TechnicalProfile:

<TechnicalProfile Id="SelfAsserted-VerifyEmail">
  <DisplayName>Verify Email</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
  </Metadata>
  <IncludeInSso>false</IncludeInSso>
  <InputClaimsTransformations>
    <InputClaimsTransformation ReferenceId="CopyEmailAddress" />
  </InputClaimsTransformations>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" />
    <InputClaim ClaimTypeReferenceId="readOnlyEmail" />
  </InputClaims>
  <DisplayClaims>
    <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
  </DisplayClaims>
</TechnicalProfile>

这个 TechnicalProfile 将 email 作为输入,将其复制到我们的 readOnlyEmail 和 InputClaimsTransformation,然后 readOnlyEmail 用于我们新的 emailVerificationControl DisplayClaim。然后,emailVerficationControl 向用户显示电子邮件的只读值,有一个发送代码的按钮,然后能够在发送后验证它。

您需要做的最后一件事是在您的 UserJourney 中使用这个新的 TechnicalProfile,OrchestrationSteps 如下所示:

<OrchestrationStep Order="X" Type="ClaimsExchange">
  <ClaimsExchanges>
    <ClaimsExchange Id="SelfAsserted-VerifyEmail-CE" TechnicalProfileReferenceId="SelfAsserted-VerifyEmail"/>
  </ClaimsExchanges>
</OrchestrationStep>

此技术解决了您遇到问题的用例。

于 2020-09-01T23:02:07.593 回答
0

我们面临同样的问题。需要自动填写电子邮件但也需要验证它。问题是填写的值立即被认为是经过验证的。

所以我们不得不做一些间接的事情。首先我们定义了一个“originalEmail”声明:

<ClaimType Id="originalEmail">
  <DisplayName>Original email</DisplayName>
  <DataType>string</DataType>
  <UserInputType>Readonly</UserInputType>
</ClaimType>

然后,注册技术配置文件定义了 2 个输入声明、2 个输入转换和 1 个输出声明(以及所有其他内容):

<InputClaimsTransformations>
  <InputClaimsTransformation ReferenceId="SetOriginalEmailFromEmail" />
  <InputClaimsTransformation ReferenceId="SetEmailToNull" />
</InputClaimsTransformations>
<InputClaims>
  <InputClaim ClaimTypeReferenceId="email" />
  <InputClaim ClaimTypeReferenceId="originalEmail" />
</InputClaims>
<OutputClaims>
  <OutputClaim ClaimTypeReferenceId="originalEmail" />
</OutputClaims>

第一个声明转换将值从 email 复制到 originalEmail:

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

第二个转换重置电子邮件声明:

<ClaimsTransformation Id="SetEmailToNull" TransformationMethod="NullClaim">
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="email" TransformationClaimType="claim_to_null" />
  </OutputClaims>
</ClaimsTransformation>

这样一来,电子邮件将首先显示为空,原始电子邮件位于其旁边的隐藏字段中。然后,您可以在自定义 UI 中使用 JavaScript 在加载时复制该值:

(function () {
    setTimeout(function () {
        copyOriginalEmailToEmail();
    }, 500);

    function copyOriginalEmailToEmail() {
        var originalEmailField = document.getElementById('originalEmail');
        var originalEmail = originalEmailField && originalEmailField.value;
        if (originalEmail) {
            document.getElementById('email').value = originalEmail;
        }
    }
}());

这是一个相当黑客,但它工作得很好。立即设置该值会导致发送代码按钮也消失,这就是延迟存在的原因。

如果有更简单的方法可以做到这一点,我也想知道:D

于 2020-09-01T06:20:31.127 回答