Compartir vía


Validar entradas de usuario mediante la directiva personalizada de Azure Active Directory B2C

La directiva personalizada de Azure Active Directory B2C (Azure AD B2C) no solo permite que las entradas de usuario sean obligatorias, sino también para validarlas. Puede marcar las entradas de usuario según sea necesario, como <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>, pero no significa que los usuarios escriban datos válidos. Azure AD B2C proporciona varias maneras de validar una entrada de usuario. En este artículo, aprenderá a escribir una directiva personalizada que recopile las entradas del usuario y las valide mediante los métodos siguientes:

  • Restrinja los datos que escribe un usuario proporcionando una lista de opciones entre las que elegir. Este enfoque usa valores enumerados, que se agregan al declarar una notificación.

  • Defina un patrón que debe coincidir una entrada de usuario. Este enfoque usa expresiones regulares, que se agregan al declarar una notificación.

  • Defina un conjunto de reglas y requiera que una entrada de usuario cumpla una o varias de las reglas. Este enfoque usa predicados, que se agregan al declarar una notificación.

  • Use el tipo de notificación especial reenterPassword para validar que el usuario ha vuelto a escribir correctamente su contraseña durante la recopilación de entradas del usuario.

  • Configure un perfil técnico de validación que defina reglas de negocio complejas que no son posibles definir en el nivel de declaración de notificación. Por ejemplo, recopilará una entrada de usuario, que debe validarse con respecto a un valor o conjunto de valores de otra notificación.

Requisitos previos

Nota

Este artículo forma parte de la Serie de guías paso a paso para crear y ejecutar sus propias directivas personalizadas en Azure Active Directory B2C. Le recomendamos que empiece esta serie por el primer artículo.

Paso 1: validar la entrada del usuario limitando las opciones de entrada del usuario

Si conoce todos los valores posibles entre los que un usuario puede escribir para una entrada determinada, puede proporcionar un conjunto finito de valores entre los que un usuario debe seleccionar. Puede usar DropdownSinglSelect, CheckboxMultiSelect y RadioSingleSelectUserInputType para este propósito. En este artículo, usará un tipo de entrada RadioSingleSelect:

  1. En VS Code, abra el archivo ContosoCustomPolicy.XML.

  2. En el elemento ClaimsSchema del archivo ContosoCustomPolicy.XML, declare el siguiente tipo de notificación:

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

    Hemos declarado la notificación accountType. Cuando se recopila el valor de la notificación del usuario, el usuario debe seleccionar Cuenta de empleado de Contoso para un valor profesional o Cuenta personal para un valor personal.

    Azure AD B2C también le permite adaptar la directiva a distintos idiomas y proporciona las restricciones de tipo de cuenta para varios idiomas. Para obtener más información, consulte el artículo Localización de la interfaz de usuario del artículo Agregar atributos de usuario.

  3. Busque el perfil técnico con Id="UserInformationCollector", agregue la notificación accountType como notificación de presentación mediante el código siguiente:

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. En el perfil técnico con Id="UserInformationCollector", agregue la notificación accountType como una salida de presentación mediante el código siguiente:

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. Para incluir la notificación de tipo de cuenta en el token de acceso, busque el RelyingParty elemento y agregue la notificación accountType como una notificación de token mediante el código siguiente:

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

Paso 2: validar la entrada del usuario mediante expresiones regulares

Cuando no es posible conocer de antemano todos los valores de entrada de usuario posibles, permite al usuario escribir los propios datos. En este caso, puede usar expresiones regulares (regex) o patrón para determinar cómo se debe dar formato a una entrada de usuario. Por ejemplo, un correo electrónico debe tener el símbolo arroba (@) y un punto (.) en algún lugar de su texto.

Al declarar una notificación, la directiva personalizada le permite definir una expresión regular, que la entrada del usuario debe coincidir. Opcionalmente, puede proporcionar un mensaje, que se muestra al usuario, si su entrada no coincide con la expresión.

  1. Busque el elemento ClaimsSchema y declare la notificación de correo electrónico mediante el código siguiente:

        <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 maurice@contoso.com"/>
            </Restriction>
        </ClaimType>
    
  2. Busque el perfil técnico con Id="UserInformationCollector", agregue la notificación de correo electrónico como notificación de presentación mediante el código siguiente:

        <DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
    
  3. En el perfil técnico con Id="UserInformationCollector", agregue la notificación de correo electrónico como una salida de presentación mediante el código siguiente:

        <OutputClaim ClaimTypeReferenceId="email"/>
    
  4. Busque el elemento RelyingParty y agregue el correo electrónico como una notificación de token mediante el código siguiente:

        <OutputClaim ClaimTypeReferenceId="email" />
    

Paso 3: validar la entrada del usuario mediante predicados

Ha usado una expresión regular para validar las entradas del usuario. Sin embargo, la expresión regular tiene una debilidad, es decir, el mensaje de error se muestra hasta que se corrige la entrada sin mostrar el requisito específico que falta la entrada.

Las validaciones de predicados permiten solucionar este problema al permitirle definir un conjunto de reglas (predicados) y un mensaje de error independiente para cada regla. En las directivas personalizadas, un predicado tiene un método integrado, que define las comprobaciones que desea realizar. Por ejemplo, puede usar el método de predicado IsLengthRange para comprobar si una contraseña de usuario está dentro del intervalo de parámetros mínimos y máximos (valores) especificados.

Mientras que los Predicates (predicados) definen la validación que se va a comparar con un tipo de notificación, PredicateValidations agrupa un conjunto de predicados para formar una validación de entrada de usuario que se puede aplicar a un tipo de notificación. Por ejemplo, se crea un grupo de predicados de validación que valida distintos tipos de caracteres permitidos para una contraseña. Tanto los elementos Predicates como PredicateValidations son elementos secundarios de la sección BuildingBlocks del archivo de directiva.

  1. Busque el elemento ClaimsSchema y declare la notificación de contraseña mediante el código siguiente:

        <ClaimType Id="password">
          <DisplayName>Password</DisplayName>
          <DataType>string</DataType>
          <AdminHelpText>Enter password</AdminHelpText>
          <UserHelpText>Enter password</UserHelpText>
          <UserInputType>Password</UserInputType>
        </ClaimType>
    
  2. Agregue un elemento Predicates como elemento secundario de la sección BuildingBlocks mediante el código siguiente. Agregue el elemento Predicates debajo del elemento ClaimsSchema:

        <Predicates>
    
        </Predicates>
    
  3. Dentro del elemento Predicates, defina predicados mediante el código siguiente:

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

    Hemos definido varias reglas, que cuando se unen se describe una contraseña aceptable. A continuación, puede agrupar predicados para formar un conjunto de directivas de contraseña que puede usar en la directiva.

  4. Agregue un elemento PredicateValidations como elemento secundario de la sección BuildingBlocks mediante el código siguiente. Agregará el elemento PredicateValidations como elemento secundario de la sección BuildingBlocks, pero por debajo del elemento Predicates:

        <PredicateValidations>
    
        </PredicateValidations>
    
  5. Dentro del elemento PredicateValidations, defina el PredicateValidations mediante el código siguiente:

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

    Hemos definido tres validaciones de predicado, StrongPassword, CustomPassword y SimplePassword. Dependiendo de las características de la contraseña que quiera que escriban los usuarios, puede usar cualquiera de las validaciones de predicado. En este artículo, usaremos una contraseña segura.

  6. Busque la declaración tipo de notificación de contraseña y agregue la validación de predicado StrongPassword justo después de la declaración del elemento UserInputType que contiene mediante el código siguiente:

        <PredicateValidationReference Id="StrongPassword" />
    
  7. Busque el perfil técnico con Id="UserInformationCollector", agregue la notificación de contraseña como notificación de presentación mediante el código siguiente:

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. En el perfil técnico con Id="UserInformationCollector", agregue la notificación de contraseña como una salida de presentación mediante el código siguiente:

        <OutputClaim ClaimTypeReferenceId="password"/>
    

Nota:

Por motivos de seguridad, no agregaremos la contraseña de un usuario como una notificación en el token generado por la directiva. Por lo tanto, no agregamos la notificación de contraseña al elemento de usuario de confianza.

Paso 4: Validar la contraseña y confirmar la contraseña

Puede requerir que los usuarios escriban su contraseña dos veces como medio para confirmar que el usuario recuerda la contraseña que escribe. En este caso, debe comprobar que los valores de las dos entradas coinciden. La directiva personalizada proporciona una manera sencilla de lograr este requisito. Los tipos de notificación password (contraseña) y reenterPassword se consideran especiales, por lo que cuando se usan para recopilar entradas de usuario, la interfaz de usuario valida que el usuario vuelva a escribir correctamente su contraseña.

Siga estos pasos para validar que la contraseña vuelva a escribir en la directiva personalizada:

  1. En la sección ClaimsSchema del archivo ContosoCustomPolicy.XML, declare la notificación reenterPassword justo después de la notificación de contraseña mediante el código siguiente:

        <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. Para recopilar la entrada de confirmación de contraseña del usuario, busque el perfil técnico autoafirmado UserInformationCollector, agregue la notificación reenterPassword como notificación de presentación mediante el código siguiente:

        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
    
  3. En el archivo ContosoCustomPolicy.XML, busque el perfil técnico autoafirmado UserInformationCollector y agregue la notificación reenterPassword como una notificación de salida con el siguiente código:

        <OutputClaim ClaimTypeReferenceId="reenterPassword"/>
    

Paso 5: carga del archivo de directiva personalizado

En este momento, ha creado la directiva para abordar los tres primeros enfoques para la validación de entrada del usuario.

Siga los pasos descritos en Carga del archivo de directiva personalizado. Si va a cargar un archivo con el mismo nombre que el que ya está en el portal, asegúrese de seleccionar Sobrescribir la directiva personalizada si ya existe.

Paso 6: prueba de la directiva personalizada

  1. En Directivas personalizadas, seleccione B2C_1A_CONTOSOCUSTOMPOLICY.

  2. Para Seleccionar aplicación en la página Información general de la directiva personalizada, seleccione la aplicación web como webapp1 que ha registrado antes. Asegúrese de que el valor Seleccionar dirección URL de respuesta está establecido en https://jwt.ms.

  3. Seleccione el botón Ejecutar ahora.

  4. Escriba el nombre propio y los apellidos.

  5. Seleccione Tipo de cuenta.

  6. Para Dirección de correo electrónico, escriba un valor de correo electrónico que no tenga un formato correcto, como maurice@contoso.

  7. En Contraseña, escriba el valor de contraseña que no obedezca todas las características de una contraseña segura establecida.

  8. Seleccione el botón Continuar. Verá una pantalla similar a la que se muestra a continuación:

    screenshot of validating user inputs.

    Debe corregir los datos antes de continuar.

  9. Escriba los valores correctos como sugieren los mensajes de error y, a continuación, vuelva a seleccionar el botón Continuar. Una vez finalizada la ejecución de la directiva, se le redirigirá a https://jwt.ms y verá un token JWT descodificado. El token tiene un aspecto similar al siguiente fragmento de código de token JWT:

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

Paso 7: validar la entrada del usuario mediante perfiles técnicos de validación

Las técnicas de validación que hemos usado en el paso 1, el paso 2 y el paso 3 no son aplicables para todos los escenarios. Si las reglas de negocio son complejas de definirse en el nivel de declaración de notificaciones, puede configurar una validación técnica y, a continuación, llamarla desde un perfil técnico autoafirmado.

Nota:

Solo los perfiles técnicos autoafirmados pueden usar perfiles técnicos de validación. Obtenga más información sobre los perfiles técnicos de validación

Información general del escenario

Es necesario que, si el tipo de cuenta del usuario es Cuenta de empleado de Contoso, debemos asegurarnos de que su dominio de correo electrónico se base en un conjunto de dominios predefinidos. Estos dominios son contoso.com, fabrikam.com y woodgrove.com. De lo contrario, se muestra un error al usuario hasta que use una cuenta de empleado de Contoso válida o cambie a Cuenta personal.

Siga los pasos siguientes para saber cómo validar la entrada del usuario mediante perfiles técnicos de validación. Use un perfil técnico de validación de tipos de transformación de notificaciones, pero también puede llamar a un servicio de API REST para validar los datos, ya que aprenderá más adelante en esta serie.

  1. En la sección ClaimsSchema del archivo ContosoCustomPolicy.XML, declare las notificaciones domain (dominio) y domainStatus mediante el código siguiente:

        <ClaimType Id="domain">
          <DataType>string</DataType>
        </ClaimType>
    
        <ClaimType Id="domainStatus">
          <DataType>string</DataType>
        </ClaimType>
    
  2. Busque la sección ClaimsTransformations y configure las transformaciones de notificaciones mediante el código siguiente:

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

    La transformación de notificaciones GetDomainFromEmail extrae un dominio del correo electrónico mediante el método ParseDomain y lo almacena en la notificación domain (dominio). La transformación de notificaciones LookupDomain usa el dominio extraído para comprobar si es válido buscándolo en los dominios predefinidos y asignando una notificación válida a domainStatus.

  3. Use el código siguiente para agregar un perfil técnico en el mismo proveedor de notificaciones que el perfil técnico con 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>
    

    Hemos declarado el perfil técnico de transformación de notificaciones, que ejecuta las transformaciones de notificaciones GetDomainFromEmail y LookupDomain .

  4. Busque el perfil técnico con Id=UserInformationCollector y un ValidationTechnicalProfile elemento justo después del elemento OutputClaims mediante el código siguiente:

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

    Hemos agregado un perfil técnico de validación al perfil técnico autoafirmado UserInformationCollector . El perfil técnico solo se omite si el valor accountType no es igual a funcionar. Si se ejecuta el perfil técnico y el dominio de correo electrónico no es válido, se produce un error.

  5. Busque el perfil técnico con Id=UserInformationCollector y agregue el código siguiente dentro de la etiqueta metadata.

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

    Hemos configurado un error personalizado en caso de que el usuario no use un correo electrónico válido.

  6. Siga las instrucciones que se describen en Cargar archivo de directiva personalizado para cargar el archivo de directiva.

  7. Siga las instrucciones del paso 6 para probar la directiva personalizada:

    1. En Tipo de cuenta, seleccione Cuenta de empleado de Contoso
    2. En Dirección de correo electrónico, escriba una dirección de correo electrónico no válida, como maurice@fourthcoffee.com.
    3. Escriba el resto de los detalles según sea necesario y seleccione Continuar.

    Desde maurice@fourthcoffee.com no será un correo electrónico válido y verá un error similar al que se muestra en la captura de pantalla siguiente. Debe usar una dirección de correo electrónico válida para ejecutar correctamente la directiva personalizada y recibir un token JWT.

    screenshot of error due to invalid email address.

Pasos siguientes