AD B2C - Как настроить индивидуальную проверку электронной почты в потоке сброса пароля

У меня есть требование настроить электронную почту, отправляемую пользователю из AD B2C, когда он / она сбрасывает пароль.

Я следовал этой документации, чтобы настроить процесс самостоятельного сброса пароля, и он отлично работает: https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-password-reset-policy?pivots=b2c-custom-policy

Чтобы предоставить фирменное письмо для сброса пароля, я следую этому коду, поскольку похоже, что единственный другой вариант - использовать элементы управления отображением, которые в настоящее время находятся в общедоступной предварительной версии (поэтому я не могу использовать их в производстве): https://github.com/azure-ad-b2c/samples/tree/master/policies/custom-email-verifcation

В файле readme четко указано, что его можно использовать также для сброса пароля, но код предоставляет только пример для подтверждения входа в систему по электронной почте.

Я попытался добавить verificationCode OutputClaim в различные TechnicalProfiles, но я не могу визуализировать настраиваемое текстовое поле verificationCode, необходимое для предоставленного кода javascript.

Я думаю, что, возможно, мне следует использовать конкретное ContentDefinition, но я действительно изо всех сил пытаюсь найти правильный способ обновить XML-код пользовательской политики.

Обновите, чтобы уточнить: в примере регистрации код подтверждения добавлен в LocalAccountSignUpWithLogonEmail TechnicalProfile:

<ClaimsProvider>
        <DisplayName>Local Account</DisplayName>
        <TechnicalProfiles>
          <TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
              <DisplayName>Email signup</DisplayName>
              <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
              <Metadata>
                <!-- Demo: Disable the email verification-->
                <Item Key="EnforceEmailVerification">False</Item>
              </Metadata>
              <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="objectId"/>
                <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true"/>
                
                <!--Demo: Add the verification code claim type-->
                <OutputClaim ClaimTypeReferenceId="verificationCode" Required="true"/>

Поскольку я работаю над сбросом пароля (управляемым следующим SubJourney), мы видим, что он ссылается на LocalAccountDiscoveryUsingEmailAddress TechnicalProfile на первом этапе:

    <SubJourney Id="PasswordReset" Type="Call">
          <OrchestrationSteps>
            <!--Sample: Validate user's email address. Run this step only when user resets the password-->
            <OrchestrationStep Order="1" Type="ClaimsExchange">
              <ClaimsExchanges>
                <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress" />
              </ClaimsExchanges>
            </OrchestrationStep>
    
            <!--Sample: Collect and persist a new password. Run this step only when user resets the password-->
            <OrchestrationStep Order="2" Type="ClaimsExchange">
              <ClaimsExchanges>
                <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
              </ClaimsExchanges>
            </OrchestrationStep>
          </OrchestrationSteps>
        </SubJourney>

Поэтому я добавил verificationCode в LocalAccountDiscoveryUsingEmailAddress TechnicalProfile:

    <!-- This technical profile forces the user to verify the email address that they provide on the UI. Only after email is verified, the user account is
    read from the directory. -->
    <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
      <DisplayName>Reset password using email address</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.localaccountpasswordreset</Item>
        <Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
      </CryptographicKeys>
      <IncludeInSso>false</IncludeInSso>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="verificationCode" Required="true"/>
        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
        <OutputClaim ClaimTypeReferenceId="objectId" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
      </OutputClaims>
      <ValidationTechnicalProfiles>
        <ValidationTechnicalProfile ReferenceId="REST-EmailVerification"/>
        <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
      </ValidationTechnicalProfiles>
    </TechnicalProfile>

Но связанный TextBox не отображается на странице.

Обновление 2: я выяснил, почему текстовое поле не отображается. Это связано с использованным ContentDefinition. При использовании определения содержимого api.selfasserted.profileupdate, несмотря на api.localaccountpasswordreset, поле отображается. Сейчас все еще работаю над этим.

Обновление 3: мне удалось заставить его работать, используя определение api.selfasserted.profileupdatecontent. Я опубликую полное решение, как только завершу интеграцию с API проверки.


person McBodge    schedule 19.03.2021    source источник


Ответы (2)


Замените verified.email выходное требование ссылкой на ваш displayControl в техническом профиле для сброса пароля, который равен LocalAccountDiscoveryUsingEmailAddress. https://docs.microsoft.com/en-us/azure/active-directory-b2c/custom-email-sendgrid#make-a-reference-to-the-displaycontrol

По сути, это те же самые шаги, за исключением того, что вы вносите изменение ссылки в технический профиль LocalAccountDiscoveryUsingEmailAddress, чтобы отобразить элемент управления отображением на этой конкретной странице, который упоминается в Шаге 1 процедуры сброса пароля для сбора и проверки электронной почты пользователей.

        <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
          <DisplayName>Reset password using email address</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.localaccountpasswordreset</Item>
            <Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
          </Metadata>
          <CryptographicKeys>
            <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
          </CryptographicKeys>
          <IncludeInSso>false</IncludeInSso>
          <DisplayClaims>
            <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
          </DisplayClaims>
          <OutputClaims>
            <!--<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />-->
            <OutputClaim ClaimTypeReferenceId="email" />
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" />

И если вам нужен другой шаблон электронной почты для сброса пароля по сравнению с Sign Up, воссоздайте новый displayControl и укажите другой шаблон.

person Jas Suri - MSFT    schedule 19.03.2021
comment
Привет, Джас, спасибо за ваш ответ, но это не применимо к моему сценарию: я использую способ javascript для управления кодом verifyCode, поскольку DisplayControls в настоящее время находятся в общедоступной предварительной версии, и я не должен использовать их в производстве: github.com/azure-ad-b2c/samples/tree / master / policy / В нем говорится, что решение для пользовательской проверки электронной почты позволяет вам отправлять собственную проверку электронной почты во время регистрации или сброса пароля на пути пользователя. Принужден ли я использовать элементы управления дисплеем со встроенной процедурой сброса пароля? - person McBodge; 19.03.2021
comment
к вашему сведению, я обновил первый пост, чтобы уточнить, что я пытался сделать. - person McBodge; 19.03.2021
comment
Мы настоятельно рекомендуем нашу общедоступную предварительную версию управления отображением поверх образца JavaScript. В этом образце есть известные уязвимости (как мы заявляли), поскольку он управляется клиентом. И да, если вы действительно хотите использовать этот старый образец, вам нужно настроить таргетинг на конкретное определение содержимого для технического профиля страницы сброса пароля. - person Jas Suri - MSFT; 20.03.2021

Решением было использовать определение содержимого api.selfasserted.profileupdate (вместо api.localaccountpasswordreset) для LocalAccountDiscoveryUsingEmailAddress технического профиля.

        <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
          <DisplayName>Reset password using email address</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.selfasserted.profileupdate</Item>
            <Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
            <Item Key="EnforceEmailVerification">false</Item>
          </Metadata>
          <CryptographicKeys>
            <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
          </CryptographicKeys>
          <IncludeInSso>false</IncludeInSso>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
            <OutputClaim ClaimTypeReferenceId="verificationCode" Required="true" />
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" />
          </OutputClaims>
          <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="REST-EmailVerification" />
            <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
          </ValidationTechnicalProfiles>
        </TechnicalProfile>

В основном это выглядит как обходной путь, но это единственный вариант не использовать функции предварительного просмотра элементов управления дисплеем.

Для дополнительной защиты проверки в техническом профиле проверки REST-EmailVerification есть проверка на стороне API, которая повторно проверяет код, ранее проверенный на стороне клиента:

          <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="REST-EmailVerification" />
            <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
          </ValidationTechnicalProfiles>

Кроме того, в настоящее время я добавляю капчу, чтобы избежать злоупотреблений логикой отправки.

Как только элементы управления дисплеем станут общедоступными, я порекомендую своему клиенту их использовать.

Причина, по которой он не работал с определением содержимого для сброса пароля, заключается в том, что он не поддерживает другие настраиваемые поля: https://docs.microsoft.com/it-it/azure/active-directory-b2c/contentdefinitions  введите описание изображения здесь

person McBodge    schedule 22.03.2021
comment
Интересно, что за то, что я действительно ответил на вопрос, проголосовали против. Я четко заявил, что - цитирую себя из первого вопроса - единственный другой вариант - использовать элементы управления отображением, которые в настоящее время находятся в общедоступной предварительной версии (поэтому я не могу использовать их в производстве). то есть я буквально не могу использовать функции предварительного просмотра в производственной среде для политики компании, поэтому это был единственный способ заставить его работать - и он работает так, как ожидалось. - person McBodge; 23.03.2021