Azure AD B2C - заполнение электронной почты во входном утверждении с предыдущего шага оркестрации и Verify.email не работает вместе с

Первый шаг оркестровки - это запрос на выход электронной почты для входа в систему. Второй шаг - это проверка электронной почты. Я хочу заполнить электронную почту из входа и подтвердить с помощью OTP электронной почты.

Проблема - Если адрес электронной почты заполнен, кнопка подтверждения не появляется. Если появляется кнопка подтверждения, адрес электронной почты не заполняется.

2 ответа

Мне удалось решить этот вариант использования, используя DisplayControl в DisplayClaim вместо использования Verified.Email в OutputClaim.

Сначала определите эти два атрибута в своих 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>

Мы собираемся скопировать атрибут электронной почты в атрибут readOnlyEmail, чтобы мы могли отобразить его на экране, а атрибут verifyCode используется при проверке одноразового пароля (OTP) электронной почты. Оставайся здесь со мной.

Определите ClaimsTransformation внутри BuildingBlocks, ClaimsTransformations, который копирует электронное письмо в 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>

Измените элемент DataUri в ContentDefinition для api.selfasserted, сделав его версией 2.0.0 и включив тег "контракт". Вы должны сделать это, чтобы DisplayClaims работал.

ContentDefinition api.selfasserted теперь должен выглядеть так:

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

Единственное изменение здесь касается элемента DataUri в ContentDefinition. Обратите внимание, что мы обновили его, добавив слово "контракт", и теперь это версия 2.0.0.

Затем определите DisplayControl внутри BuildingBlocks, DisplayControls, который использует наш readOnlyEmail и verficationCode ClaimTypes:

<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 для verifyCode предназначен для сбора одноразового пароля после его отправки на вашу электронную почту.

Также обратите внимание на действия, которые указывают на технические профили, которые нам еще предстоит определить. Они соответствуют кнопкам на экране и отправят электронное письмо и подтвердят код. Давайте определимся с ними дальше. Вы можете поместить их в любой 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>

Эти технические профили используют AadSsprProtocolProvider для отправки и проверки кода. У MS есть хорошая документация: https://docs.microsoft.com/en-us/azure/active-directory-b2c/aad-sspr-technical-profile

Почти готово. Теперь давайте создадим SelfAssertedAttributeProvider TechnicalProfile, чтобы воспользоваться преимуществами нашего нового DisplayClaim, который будет выполнять встроенную проверку.

Создайте этот TechnicalProfile в любом ClaimsProvider, который вам нужен:

<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 примет электронную почту в качестве входных данных, скопирует ее в наш readOnlyEmail с InputClaimsTransformation, а затем readOnlyEmail будет использоваться в нашем новом emailVerificationControl DisplayClaim. Затем этот emailVerficationControl показывает пользователю значение электронной почты только для чтения, имеет кнопку для отправки кода, а затем возможность проверить его после отправки.

Последнее, что вам нужно сделать, это использовать этот новый TechnicalProfile в своем UserJourney, OrchestrationSteps следующим образом:

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

Этот метод решает случай использования, с которым у вас возникли проблемы. Надеюсь, это было полезно! Пожалуйста, не стесняйтесь комментировать ниже с вопросами.

Мы столкнулись с той же проблемой. Необходимо для автоматического заполнения электронной почты, а также для проверки ее. Проблема в том, что введенное значение сразу считается проверенным.

Так что нам пришлось сделать это немного косвенно. Сначала мы определили утверждение "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>

Первое преобразование утверждения копирует значение из электронной почты в 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>

Таким образом, электронное письмо сначала будет отображаться пустым, а исходное письмо будет в скрытом поле рядом с ним. Затем вы можете использовать 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

Другие вопросы по тегам