Validar entradas de usuário usando a política personalizada do Azure Ative Directory B2C
A política personalizada do Azure Ative Directory B2C (Azure AD B2C) não só permite tornar as entradas do usuário obrigatórias, mas também validá-las. Você pode marcar as entradas do usuário conforme necessário, como <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>
, mas isso não significa que os usuários inserirão dados válidos. O Azure AD B2C fornece várias maneiras de validar uma entrada do usuário. Neste artigo, você aprenderá a escrever uma política personalizada que coleta as entradas do usuário e as valida usando as seguintes abordagens:
Restrinja os dados inseridos por um usuário fornecendo uma lista de opções para escolher. Essa abordagem usa Valores Enumerados, que você adiciona quando declara uma declaração.
Defina um padrão que uma entrada do usuário deve corresponder. Essa abordagem usa expressões regulares, que você adiciona quando declara uma declaração.
Defina um conjunto de regras e exija que uma entrada do usuário obedeça a uma ou mais das regras. Essa abordagem usa Predicados, que você adiciona quando declara uma reivindicação.
Use o tipo de declaração especial reenterPassword para validar se o usuário reinseriu corretamente sua senha durante a coleta de entrada do usuário.
Configure um Perfil Técnico de Validação que defina regras de negócios complexas que não são possíveis de definir no nível da declaração de declaração. Por exemplo, você coleta uma entrada de usuário, que precisa ser validada em relação a um valor ou valores definidos em outra declaração.
Pré-requisitos
Se você ainda não tiver um, crie um locatário do Azure AD B2C vinculado à sua assinatura do Azure.
Registre um aplicativo Web e habilite a concessão implícita de token de ID. Para o URI de redirecionamento, use https://jwt.ms.
Você deve ter o Visual Studio Code (VS Code) instalado no seu computador.
Conclua as etapas em Coletar e manipular entradas de usuário usando a política personalizada do Azure AD B2C. Este artigo faz parte da série de guias de instruções Criar e executar suas próprias políticas personalizadas.
Nota
Este artigo faz parte da série de guias de instruções Criar e executar suas próprias políticas personalizadas no Azure Ative Directory B2C. Recomendamos que comece esta série a partir do primeiro artigo.
Etapa 1 - Validar a entrada do usuário limitando as opções de entrada do usuário
Se você souber todos os valores possíveis que um usuário pode inserir para uma determinada entrada, poderá fornecer um conjunto finito de valores que um usuário deve selecionar. Você pode usar DropdownSinglSelect, CheckboxMultiSelect e RadioSingleSelect UserInputType para essa finalidade. Neste artigo, você usará um tipo de entrada RadioSingleSelect :
No VS Code, abra o arquivo
ContosoCustomPolicy.XML
.ClaimsSchema
No elemento do arquivo, declare o seguinte tipo deContosoCustomPolicy.XML
declaração:<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>
Nós declaramos a reivindicação accountType . Quando o valor da declaração é coletado do usuário, o usuário deve selecionar Conta de Funcionário da Contoso para um trabalho de valor ou Conta Pessoal para um valor pessoal.
O Azure AD B2C também permite acomodar sua política a idiomas diferentes e fornece as restrições de tipo de conta para vários idiomas. Para obter mais informações, consulte o artigo Localizar a interface do usuário do artigo Adicionar atributos do usuário.
Localize o perfil técnico com
Id="UserInformationCollector"
, adicione a declaração accountType como declaração de exibição usando o seguinte código:<DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
No perfil técnico com
Id="UserInformationCollector"
, adicione a declaração accountType como uma declaração de saída usando o seguinte código:<OutputClaim ClaimTypeReferenceId="accountType"/>
Para incluir a declaração de tipo de conta no token de acesso, localize o elemento , adicione a declaração accountType como uma declaração de token usando o
RelyingParty
seguinte código:<OutputClaim ClaimTypeReferenceId="accountType" />
Etapa 2 - Validar a entrada do usuário usando expressões regulares
Quando não é possível saber todos os valores de entrada possíveis do usuário com antecedência, você permite que o usuário insira os próprios dados. Nesse caso, você pode usar expressões regulares (regex) ou padrão para ditar como uma entrada do usuário precisa ser formatada. Por exemplo, um e-mail deve ter o símbolo at (@) e um ponto (.) em algum lugar em seu texto.
Quando você declara uma declaração, a política personalizada permite que você defina um regex, que a entrada do usuário deve corresponder. Opcionalmente, você pode fornecer uma mensagem, que é mostrada ao usuário, se a entrada não corresponder à expressão.
Localize o elemento e declare a declaração de e-mail usando o
ClaimsSchema
seguinte código:<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.!#$%&'^_`{}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" HelpText="Please enter a valid email address something like maurice@contoso.com"/> </Restriction> </ClaimType>
Localize o perfil técnico com
Id="UserInformationCollector"
, adicione a declaração de e-mail como declaração de exibição usando o seguinte código:<DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
No perfil técnico com
Id="UserInformationCollector"
, adicione a declaração de e-mail como uma declaração de saída usando o seguinte código:<OutputClaim ClaimTypeReferenceId="email"/>
Localize o elemento , adicione o e-mail como uma declaração de token usando o
RelyingParty
seguinte código:<OutputClaim ClaimTypeReferenceId="email" />
Etapa 3 - Validar a entrada do usuário usando predicados
Você usou o regex para validar as entradas do usuário. No entanto, o regex tem um ponto fraco, ou seja, a mensagem de erro é exibida até que você corrija a entrada sem mostrar o requisito específico que a entrada está faltando.
As validações de predicados permitem resolver esse problema, permitindo que você defina um conjunto de regras (predicados) e uma mensagem de erro independente para cada regra. Em políticas personalizadas, um predicado tem um método embutido, que define as verificações que você deseja fazer. Por exemplo, você pode usar o método de predicado IsLengthRange para verificar se uma senha de usuário está dentro do intervalo de parâmetros mínimos e máximos (valores) especificados.
Enquanto os Predicados definem a validação para verificar em relação a um tipo de declaração, os PredicateValidations agrupam um conjunto de predicados para formar uma validação de entrada do usuário que pode ser aplicada a um tipo de declaração. Por exemplo, você cria um grupo de predicados de validação que valida diferentes tipos de caracteres permitidos para uma senha. Os elementos Predicados e PredicateValidations são elementos filho da seção do BuildingBlocks
seu arquivo de política.
Localize o elemento e declare a declaração de senha usando o
ClaimsSchema
seguinte código:<ClaimType Id="password"> <DisplayName>Password</DisplayName> <DataType>string</DataType> <AdminHelpText>Enter password</AdminHelpText> <UserHelpText>Enter password</UserHelpText> <UserInputType>Password</UserInputType> </ClaimType>
Adicione um
Predicates
elemento como filho daBuildingBlocks
seção usando o código a seguir. Você adiciona oPredicates
elemento abaixo doClaimsSchema
elemento :<Predicates> </Predicates>
Dentro do
Predicates
elemento , defina predicados usando o seguinte código:<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">@#$%^&*\-_+=[]{}|\\:',.?/`~"();!</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@#$%^&*\-_+=[\]{}|\\:',?/`~"();! ]|(\.(?!@)))+$)|(^$)</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>
Definimos várias regras que, quando juntas, descreviam uma senha aceitável. Em seguida, você pode agrupar predicados para formar um conjunto de políticas de senha que você pode usar em sua política.
Adicione um
PredicateValidations
elemento como filho daBuildingBlocks
seção usando o código a seguir. Você adiciona oPredicateValidations
elemento como filho daBuildingBlocks
seção, mas abaixo doPredicates
elemento :<PredicateValidations> </PredicateValidations>
Dentro do
PredicateValidations
elemento , defina PredicateValidations usando o seguinte código:<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>
Temos três Validação de Predicados definidos, StrongPassword, CustomPassword e SimplePassword. Dependendo das características da senha que você deseja que seus usuários insiram, você pode usar qualquer uma nas Validações de Predicados. Neste artigo, usaremos uma senha forte.
Localize a declaração de tipo de declaração de senha e adicione a validação de predicado StrongPassword logo após a declaração de elemento UserInputType que ela contém usando o seguinte código:
<PredicateValidationReference Id="StrongPassword" />
Localize o perfil técnico com
Id="UserInformationCollector"
, adicione a declaração de senha como declaração de exibição usando o seguinte código:<DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
No perfil técnico com
Id="UserInformationCollector"
, adicione a declaração de senha como uma declaração de saída usando o seguinte código:<OutputClaim ClaimTypeReferenceId="password"/>
Nota
Por motivos de segurança, não adicionaremos a senha de um usuário como uma declaração no token gerado pela sua política. Portanto, não adicionamos a declaração de senha ao elemento de terceira parte confiável.
Passo 4 - Validar palavra-passe e confirmar palavra-passe
Você pode exigir que os usuários insiram a senha duas vezes como forma de confirmar que o usuário se lembra da senha inserida. Nesse caso, você deve verificar se os valores das duas entradas coincidem. A política personalizada fornece uma maneira fácil de atingir esse requisito. Os tipos de declaração password e reenterPassword são considerados especiais, portanto, quando são usados para coletar entradas do usuário, a interface do usuário valida que o usuário reinseriu corretamente sua senha.
Use as seguintes etapas para validar a reinserção da senha em sua política personalizada:
Na seção
ClaimsSchema
do seuContosoCustomPolicy.XML
arquivo, declare a declaração reenterPassword logo após a declaração de senha usando o seguinte código:<ClaimType Id="reenterPassword"> <DisplayName>Confirm new password</DisplayName> <DataType>string</DataType> <AdminHelpText>Confirm new password</AdminHelpText> <UserHelpText>Reenter password</UserHelpText> <UserInputType>Password</UserInputType> </ClaimType>
Para coletar a entrada de confirmação de senha do usuário, localize o perfil técnico autodeclarado, adicione a declaração reenterPassword como uma declaração de exibição usando o
UserInformationCollector
seguinte código:<DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
Em seu
ContosoCustomPolicy.XML
arquivo, localize o perfil técnico autodeclarado, adicione a declaração reenterPassword como uma declaração de saída usando oUserInformationCollector
seguinte código:<OutputClaim ClaimTypeReferenceId="reenterPassword"/>
Etapa 5 - Carregar arquivo de política personalizado
Neste ponto, você criou sua política para abordar as três primeiras abordagens à validação de entrada do usuário.
Siga as etapas em Carregar arquivo de política personalizado. Se você estiver carregando um arquivo com o mesmo nome que o que já está no portal, certifique-se de selecionar Substituir a política personalizada, se ela já existir.
Etapa 6 - Testar a política personalizada
Em Políticas personalizadas, selecione B2C_1A_CONTOSOCUSTOMPOLICY.
Para Selecionar aplicativo na página de visão geral da política personalizada, selecione o aplicativo Web, como webapp1 , que você registrou anteriormente. Certifique-se de que o valor Select reply URL está definido como
https://jwt.ms
.Selecione o botão Executar agora .
Introduza o Nome Próprio e o Apelido.
Selecione Tipo de conta.
Em Endereço de e-mail, insira um valor de e-mail que não esteja bem formatado, como maurice@contoso.
Em Senha, digite o valor da senha que não obedece a todas as características de uma senha forte, conforme definido.
Selecione o botão Continuar . Você verá uma tela semelhante à mostrada abaixo:
Você deve corrigir suas entradas antes de continuar.
Insira os valores corretos conforme sugerido pelas mensagens de erro e selecione o botão Continuar novamente. Depois que a política terminar a execução, você será redirecionado para
https://jwt.ms
o , e verá um token JWT decodificado. O token é semelhante ao seguinte trecho 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]
Etapa 7 - Validar a entrada do usuário usando perfis técnicos de validação
As técnicas de validação que usamos nas etapas 1, 2 e 3 não são aplicáveis a todos os cenários. Se suas regras de negócios forem complexas de serem definidas no nível da declaração de declaração, você poderá configurar um Técnico de Validação e, em seguida, chamá-lo de um Perfil Técnico Autodeclarado.
Nota
Apenas perfis técnicos autoafirmados podem usar perfis técnicos de validação. Saiba mais sobre o perfil técnico de validação
Descrição geral do cenário
Exigimos que, se o Tipo de Conta do usuário for Conta de Funcionário da Contoso, devemos garantir que seu domínio de email seja baseado em um conjunto de domínios predefinidos. Esses domínios são contoso.com, fabrikam.com e woodgrove.com. Caso contrário, mostraremos um erro ao usuário até que ele use uma Conta de Funcionário da Contoso válida ou mude para Conta Pessoal.
Use as etapas a seguir para saber como validar a entrada do usuário usando perfis técnicos de validação. Você usa um perfil técnico de validação de tipo de transformação de declarações, mas também pode chamar um serviço de API REST para validar dados, como aprenderá mais adiante nesta série.
ClaimsSchema
Na seção do arquivoContosoCustomPolicy.XML
, declare as declarações domain e domainStatus usando o seguinte código:<ClaimType Id="domain"> <DataType>string</DataType> </ClaimType> <ClaimType Id="domainStatus"> <DataType>string</DataType> </ClaimType>
Localize a
ClaimsTransformations
seção e configure as transformações de declarações usando o seguinte código:<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>
A transformação de declarações GetDomainFromEmail extrai um domínio do email usando o método ParseDomain e o armazena na declaração de domínio . A Transformação de Declarações LookupDomain usa o domínio extraído para verificar se ele é válido, pesquisando-o nos domínios predefinidos e atribuindo válido à reivindicação domainStatus .
Use o código a seguir para adicionar um perfil técnico no mesmo provedor de declarações que o perfil técnico com
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>
Declaramos o perfil técnico de transformação de declarações, que executa as transformações de declarações GetDomainFromEmail e LookupDomain .
Localize o perfil técnico com
Id=UserInformationCollector
, e umValidationTechnicalProfile
logo após o elemento usando oOutputClaims
seguinte código:<ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="CheckCompanyDomain"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="false"> <Value>accountType</Value> <Value>work</Value> <Action>SkipThisValidationTechnicalProfile</Action> </Precondition> </Preconditions> </ValidationTechnicalProfile> </ValidationTechnicalProfiles>
Adicionamos um Perfil Técnico de Validação ao perfil técnico autodeclarado UserInformationCollector . O perfil técnico é ignorado somente se o valor accountType não for igual ao trabalho. Se o perfil técnico for executado e o domínio de e-mail não for válido, gerou um erro.
Localize o perfil técnico com
Id=UserInformationCollector
, e adicione o seguinte código dentro dametadata
tag .<Item Key="LookupNotFound">The provided email address isn't a valid Contoso Employee email.</Item>
Configuramos um erro personalizado caso o usuário não use um e-mail válido.
Siga as instruções em Carregar arquivo de política personalizado para carregar seu arquivo de política.
Siga as instruções na etapa 6 para testar sua política personalizada:
- Em Tipo de Conta, selecione Conta de Funcionário da Contoso
- Em Endereço de e-mail, insira um endereço de e-mail inválido, como maurice@fourthcoffee.com.
- Insira o restante dos detalhes conforme necessário e selecione Continuar
Como maurice@fourthcoffee.com não é um e-mail válido, você verá um erro semelhante ao mostrado na captura de tela abaixo. Você deve usar um endereço de e-mail válido para executar com êxito a política personalizada e receber um token JWT.
Próximos passos
Saiba mais sobre o perfil técnico de validação.