Поделиться через


Проводите проверку ввода пользователей с помощью индивидуальной политики в Azure Active Directory B2C

Настраиваемая политика Azure Active Directory B2C (Azure AD B2C) позволяет не только выполнять обязательные входные данные пользователей, но и проверять их. Вы можете пометить входные данные пользователей как необходимые, например, <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>, но это не означает, что пользователи будут вводить корректные данные. Azure AD B2C предоставляет различные способы проверки входных данных пользователей. В этой статье вы узнаете, как написать пользовательскую политику, которая собирает входные данные пользователя и проверяет их с помощью следующих подходов:

  • Ограничить ввод данных, предоставив список параметров для выбора. Этот подход использует перечисленные значения, которые вы добавляете при заявлении требования.

  • Определите шаблон, который должен соответствовать входным данным пользователя. Этот подход использует регулярные выражения, которые добавляются при создании заявки.

  • Определите набор правил и требуется, чтобы входные данные пользователя подчинялись одному или нескольким правилам. Этот подход использует предикаты, которые вы добавляете при объявлении утверждения.

  • Используйте специальный тип утверждения reenterPassword для проверки правильности ввода пароля пользователем во время сбора данных пользователем.

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

Предпосылки

Примечание.

Эта статья является частью серии руководств «Создавайте и запускайте собственные пользовательские политики в Azure Active Directory B2C» . Мы рекомендуем начать эту серию из первой статьи.

Шаг 1. Проверка входных данных пользователей путем ограничения параметров ввода пользователем

Если вы знаете все возможные значения, которые пользователь может ввести для заданного ввода, можно указать конечный набор значений, которые пользователь должен выбрать. Вы можете использовать DropdownSingleSelect, CheckboxMultiSelectи RadioSingleSelectUserInputType для этой цели. В этой статье вы будете использовать тип ввода RadioSingleSelect:

  1. В VS Code откройте файл ContosoCustomPolicy.XML.

  2. В элементе ClaimsSchema файла ContosoCustomPolicy.XML объявите следующий тип утверждения:

        <ClaimType Id="accountType">
            <DisplayName>Account Type</DisplayName>
            <DataType>string</DataType>
            <UserHelpText>The type of account used by the user</UserHelpText>
            <UserInputType>RadioSingleSelect</UserInputType>
            <Restriction>
                <Enumeration Text="Contoso Employee Account" Value="work" SelectByDefault="true"/>
                <Enumeration Text="Personal Account" Value="personal" SelectByDefault="false"/>
            </Restriction>
        </ClaimType>
    

    Мы объявили тип счета запрос. Если значение утверждения получено от пользователя, пользователь должен выбрать либо учетную запись сотрудника Contoso для значения рабочая, либо личную учетную запись для значения личная.

    Azure AD B2C также позволяет разместить политику на разных языках и предоставить ограничения типа учетной записи для нескольких языков. Дополнительные сведения см. в статье Локализация пользовательского интерфейса статьи Добавление атрибутов пользователя.

  3. Найдите технический профиль с Id="UserInformationCollector", добавьте утверждение accountType как отображаемое утверждение, используя следующий код:

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. В техническом профиле с Id="UserInformationCollector"добавьте утверждение accountType в качестве выходного утверждения, используя следующий код:

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. Чтобы включить параметр типа учетной записи в токен доступа, найдите элемент RelyingParty, затем добавьте параметр accountType как параметр токена, воспользовавшись следующим кодом:

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

Шаг 2. Проверка входных данных пользователей с помощью регулярных выражений

Если заранее не удается узнать все возможные входные значения пользователей, можно разрешить пользователю вводить данные самостоятельно. В этом случае можно использовать регулярные выражения или шаблон для задания формата пользовательского ввода. Например, электронная почта должна иметь символ по адресу (@) и период (.) где-то в тексте.

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

  1. Найдите элемент ClaimsSchema и определите утверждение email, используя следующий код:

        <ClaimType Id="email">
            <DisplayName>Email Address</DisplayName>
            <DataType>string</DataType>
            <DefaultPartnerClaimTypes>
                <Protocol Name="OpenIdConnect" PartnerClaimType="email"/>
            </DefaultPartnerClaimTypes>
            <UserHelpText>Your email address. </UserHelpText>
            <UserInputType>TextBox</UserInputType>
            <Restriction>
                <Pattern RegularExpression="^[a-zA-Z0-9.!#$%&amp;&apos;^_`{}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" HelpText="Please enter a valid email address something like [email protected]"/>
            </Restriction>
        </ClaimType>
    
  2. Найдите технический профиль с Id="UserInformationCollector", добавьте утверждение электронной почты в виде отображаемого утверждения с помощью следующего кода:

        <DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
    
  3. В техническом профиле с Id="UserInformationCollector"добавьте утверждение электронной почты в качестве выходного утверждения с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="email"/>
    
  4. Найдите элемент RelyingParty, добавьте электронную почту как претензию на токен с использованием следующего кода:

        <OutputClaim ClaimTypeReferenceId="email" />
    

Шаг 3. Проверка входных данных пользователей с помощью предикатов

Вы использовали regex для проверки входных данных пользователей. Тем не менее, regex имеет одну слабость, то есть сообщение об ошибке отображается, пока вы не исправите входные данные, не показывая определенное требование, которое отсутствует.

Предикаты проверки позволяют решить эту проблему, позволяя определить набор правил (предикатов) и независимое сообщение об ошибке для каждого правила. В пользовательских политиках предикат имеет встроенный метод, который определяет проверки, которые требуется выполнить. Например, можно использовать метод предиката isLengthRange isLengthRange, чтобы проверить, находится ли пользователь пароля в диапазоне минимальных и максимальных параметров (значений).

Хотя предикаты определяют проверку для типа утверждения, PredicateValidations объединяет набор предикатов для формирования проверки пользовательского ввода, которую можно применить к типу утверждения. Например, вы создаете группу предиката проверки, которая проверяет различные типы разрешенных символов для пароля. Оба предикаты и PredicateValidations являются дочерними элементами раздела BuildingBlocks файла политики.

  1. Найдите элемент ClaimsSchema и объявите утверждение пароля с помощью следующего кода:

        <ClaimType Id="password">
          <DisplayName>Password</DisplayName>
          <DataType>string</DataType>
          <AdminHelpText>Enter password</AdminHelpText>
          <UserHelpText>Enter password</UserHelpText>
          <UserInputType>Password</UserInputType>
        </ClaimType>
    
  2. Добавьте элемент Predicates в качестве дочернего элемента BuildingBlocks раздела с помощью следующего кода. Добавьте элемент Predicates под элементом ClaimsSchema:

        <Predicates>
    
        </Predicates>
    
  3. В элементе Predicates определите предикаты с помощью следующего кода:

      <Predicate Id="IsLengthBetween8And64" Method="IsLengthRange" HelpText="The password must be between 8 and 64 characters.">
        <Parameters>
          <Parameter Id="Minimum">8</Parameter>
          <Parameter Id="Maximum">64</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Lowercase" Method="IncludesCharacters" HelpText="a lowercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">a-z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Uppercase" Method="IncludesCharacters" HelpText="an uppercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">A-Z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Number" Method="IncludesCharacters" HelpText="a digit">
        <Parameters>
          <Parameter Id="CharacterSet">0-9</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Symbol" Method="IncludesCharacters" HelpText="a symbol">
        <Parameters>
          <Parameter Id="CharacterSet">@#$%^&amp;*\-_+=[]{}|\\:',.?/`~"();!</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="PIN" Method="MatchesRegex" HelpText="The password must be numbers only.">
        <Parameters>
          <Parameter Id="RegularExpression">^[0-9]+$</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="AllowedCharacters" Method="MatchesRegex" HelpText="An invalid character was provided.">
        <Parameters>
          <Parameter Id="RegularExpression">(^([0-9A-Za-z\d@#$%^&amp;*\-_+=[\]{}|\\:',?/`~"();! ]|(\.(?!@)))+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="DisallowedWhitespace" Method="MatchesRegex" HelpText="The password must not begin or end with a whitespace character.">
        <Parameters>
          <Parameter Id="RegularExpression">(^\S.*\S$)|(^\S+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    

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

  4. Добавьте элемент PredicateValidations в качестве дочернего элемента BuildingBlocks раздела с помощью следующего кода. Элемент PredicateValidations добавляется в качестве дочернего элемента раздела BuildingBlocks, но ниже элемента Predicates:

        <PredicateValidations>
    
        </PredicateValidations>
    
  5. В элементе PredicateValidations определите PredicateValidations с помощью следующего кода:

        <PredicateValidation Id="SimplePassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="StrongPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="CharacterClasses">
                    <UserHelpText>The password must have at least 3 of the following:</UserHelpText>
                    <PredicateReferences MatchAtLeast="3">
                        <PredicateReference Id="Lowercase"/>
                        <PredicateReference Id="Uppercase"/>
                        <PredicateReference Id="Number"/>
                        <PredicateReference Id="Symbol"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="CustomPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
    

    У нас есть три определенных валидатора предикатов: StrongPassword, CustomPassword и SimplePassword. В зависимости от характеристик пароля, который требуется ввести пользователям, можно использовать любой из вариантов проверки предиката. В этой статье мы будем использовать надежный пароль.

  6. Найдите объявление типа утверждения пароля и добавьте StrongPassword Predicate Validation сразу после объявления элемента UserInputType, содержащегося в следующем коде:

        <PredicateValidationReference Id="StrongPassword" />
    
  7. Найдите технический профиль с Id="UserInformationCollector", добавьте утверждение о пароле в качестве отображаемого утверждения с помощью следующего кода:

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. В техническом профиле с Id="UserInformationCollector"добавьте утверждение для пароля как выходное утверждение с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="password"/>
    

Примечание.

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

Шаг 4. Проверка пароля и подтверждение пароля

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

Чтобы проверить повторный ввод пароля в вашей настраиваемой политике, выполните следующие действия.

  1. В разделе ClaimsSchema файла ContosoCustomPolicy.XML объявите переменную reenterPassword сразу после переменной пароль, используя следующий код:

        <ClaimType Id="reenterPassword">
            <DisplayName>Confirm new password</DisplayName>
            <DataType>string</DataType>
            <AdminHelpText>Confirm new password</AdminHelpText>
            <UserHelpText>Reenter password</UserHelpText>
            <UserInputType>Password</UserInputType>
        </ClaimType>    
    
  2. Чтобы получить входные данные подтверждения пароля от пользователя, найдите UserInformationCollector самоподтвержденный технический профиль, добавьте повторное утверждение пароля в качестве отображаемого утверждения с помощью следующего кода:

        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
    
  3. В файле ContosoCustomPolicy.XML найдите UserInformationCollector самостоятельно заявленный технический профиль, добавьте утверждение повторного ввода пароля в виде выходного утверждения с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="reenterPassword"/>
    

Шаг 5. Отправка пользовательского файла политики

На этом этапе вы создали политику для решения первых трех подходов к проверке ввода пользователей.

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

Шаг 6. Проверка настраиваемой политики

  1. В разделе Настраиваемые политикивыберите B2C_1A_CONTOSOCUSTOMPOLICY.

  2. Чтобы Выбрать приложение на странице обзора настраиваемой политики, выберите веб-приложение, например webapp1, зарегистрированное ранее. Убедитесь, что для параметра Select reply URL задано значениеhttps://jwt.ms.

  3. Нажмите кнопку «Запустить».

  4. Введите имя и фамилию .

  5. Выберите тип учетной записи.

  6. Для адреса электронной почтывведите значение электронной почты, которое не хорошо отформатировано, например maurice@contoso.

  7. Для парольвведите значение пароля, которое не соответствует всем требованиям к надежным паролям, как задано.

  8. Нажмите кнопку "Продолжить ". Вы увидите экран, аналогичный приведенному ниже:

    снимок экрана: проверка входных данных пользователей.

    Перед продолжением необходимо исправить входные данные.

  9. Введите правильные значения, как указано в сообщениях об ошибках, а затем нажмите кнопку Продолжить еще раз. После завершения выполнения политики вы будете перенаправлены на https://jwt.ms, и вы увидите декодированную JWT. Маркер выглядит примерно так, как показано в следующем фрагменте кода JWT:

    {
      "typ": "JWT",
      "alg": "RS256",
      "kid": "pxLOMWFg...."
    }.{
      ...
      "sub": "c7ae4515-f7a7....",
      ...
      "acr": "b2c_1a_contosocustompolicy",
      "accountType": "work",
      ...
      "email": "[email protected]",
      "name": "Maurice Paulet",
      "message": "Hello Maurice Paulet"
    }.[Signature]

Шаг 7. Проверка входных данных пользователей с помощью технических профилей проверки

Методы проверки, которые мы использовали на шаге 1, шаге 2 и шаге 3, не применимы для всех сценариев. Если правила бизнеса слишком сложны для определения на уровне декларации претензий, можно настроить техническую проверку, а затем вызвать её из Self-Asserted технического профиля.

Примечание.

Только самоутвержденные технические профили могут использовать технические профили проверки. Дополнительные сведения о техническом профиле проверки

Обзор сценария

Мы требуем, чтобы, если типа учетной записи пользователя является учетной записью сотрудника Contoso, домен их электронной почты принадлежал к набору предопределенных доменов. Эти домены contoso.com, fabrikam.comи woodgrove.com. В противном случае мы показываем ошибку пользователю, пока не будет использована допустимая учетная запись сотрудника Contoso или пока они не переключатся на личную учетную запись.

Чтобы узнать, как проверить входные данные пользователей с помощью технических профилей проверки, выполните следующие действия. Вы используете технический профиль проверки типа преобразования утверждений, но вы также можете вызвать службу REST API для проверки данных, как описано далее в этой серии.

  1. В разделе ClaimsSchema файла ContosoCustomPolicy.XML объявите домена и утверждения domainStatus с помощью следующего кода:

        <ClaimType Id="domain">
          <DataType>string</DataType>
        </ClaimType>
    
        <ClaimType Id="domainStatus">
          <DataType>string</DataType>
        </ClaimType>
    
  2. Найдите раздел ClaimsTransformations и настройте преобразования утверждений с помощью следующего кода:

        <ClaimsTransformation Id="GetDomainFromEmail" TransformationMethod="ParseDomain">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="emailAddress"/>
            </InputClaims>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domain" TransformationClaimType="domain"/>
            </OutputClaims>
        </ClaimsTransformation>
        <ClaimsTransformation Id="LookupDomain" TransformationMethod="LookupValue">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="domain" TransformationClaimType="inputParameterId"/>
            </InputClaims>
            <InputParameters>
                <InputParameter Id="contoso.com" DataType="string" Value="valid"/>
                <InputParameter Id="fabrikam.com" DataType="string" Value="valid"/>
                <InputParameter Id="woodgrove.com" DataType="string" Value="valid"/>
                <InputParameter Id="errorOnFailedLookup" DataType="boolean" Value="true"/>
            </InputParameters>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domainStatus" TransformationClaimType="outputClaim"/>
            </OutputClaims>
        </ClaimsTransformation>
    

    Преобразование утверждений GetDomainFromEmail извлекает домен из электронной почты, используя метод ParseDomain, и сохраняет его в утверждение domain. Преобразование утверждений LookupDomain использует извлеченный домен, чтобы проверить его допустимость, проверяя его наличие в предопределенных доменах, и затем присваивает значение допустимо утверждению domainStatus.

  3. Используйте следующий код для добавления технического профиля в того же поставщика утверждений, что и технический профиль с Id=UserInformationCollector.

        <TechnicalProfile Id="CheckCompanyDomain">
            <DisplayName>Check Company validity </DisplayName>
            <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            <InputClaimsTransformations>
                <InputClaimsTransformation ReferenceId="GetDomainFromEmail"/>
            </InputClaimsTransformations>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domain"/>
            </OutputClaims>
            <OutputClaimsTransformations>
                <OutputClaimsTransformation ReferenceId="LookupDomain"/>
            </OutputClaimsTransformations>
        </TechnicalProfile>
    

    Мы объявили технический профиль преобразования утверждений, который выполняет преобразования утверждений GetDomainFromEmail и LookupDomain.

  4. Найдите технический профиль с Id=UserInformationCollectorи ValidationTechnicalProfile сразу после элемента OutputClaims с помощью следующего кода:

        <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="CheckCompanyDomain">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>accountType</Value>
                        <Value>work</Value>
                        <Action>SkipThisValidationTechnicalProfile</Action>
                    </Precondition>
                </Preconditions>
            </ValidationTechnicalProfile>
        </ValidationTechnicalProfiles>
    

    Мы добавили технический профиль проверки в самоудостоверяемый технический профиль UserInformationCollector. Технический профиль пропускается, только если значение accountType не равно work. Если технический профиль выполняется, а домен электронной почты недействителен, возникает ошибка.

  5. Найдите технический профиль с Id=UserInformationCollectorи добавьте следующий код в тег metadata.

        <Item Key="LookupNotFound">The provided email address isn't a valid Contoso Employee email.</Item>
    

    Мы настроили настраиваемую ошибку в случае, если пользователь не использует допустимый адрес электронной почты.

  6. Следуйте инструкциям в Загрузке кастомного файла политики для загрузки вашего файла политики.

  7. Следуйте инструкциям в шаге 6 , чтобы протестировать настраиваемую политику.

    1. Для типа учетной записи выберите учетную запись сотрудника Contoso
    2. Для адреса электронной почтывведите недопустимый адрес электронной почты, например [email protected].
    3. Введите остальные сведения по мере необходимости и выберите Продолжить

    Так как [email protected] не является допустимым сообщением электронной почты, вы увидите ошибку, аналогичную той, которая показана на снимке экрана ниже. Для успешного выполнения настраиваемой политики и получения JWT необходимо использовать допустимый адрес электронной почты.

    снимок экрана ошибки из-за недопустимого адреса электронной почты.