Trabalhar com identidades baseadas em declaraçõesWork with claims-based identities

Código de exemplo do GitHubGitHub Sample code

Declarações no Azure ADClaims in Azure AD

Quando um usuário faz logon, o Microsoft Azure AD envia um token de ID que contém um conjunto de declarações sobre o usuário.When a user signs in, Azure AD sends an ID token that contains a set of claims about the user. Uma declaração é simplesmente uma informação expressada como um par chave/valor.A claim is simply a piece of information, expressed as a key/value pair. Por exemplo, email=bob@contoso.com.For example, email=bob@contoso.com. Declarações têm um emissor — nesse caso, o Azure AD —, que é a entidade que autentica o usuário e cria as declarações.Claims have an issuer — in this case, Azure AD — which is the entity that authenticates the user and creates the claims. Você confia nas declarações porque confia no emissor.You trust the claims because you trust the issuer. (Por outro lado, se você não confiar o emissor, não confiará nas declarações.)(Conversely, if you don't trust the issuer, don't trust the claims!)

Em um alto nível:At a high level:

  1. O usuário é autenticado.The user authenticates.
  2. O IDP (provedor de identidade) envia um conjunto de declarações.The Identity Provider (IDP) sends a set of claims.
  3. O aplicativo normaliza ou amplia as declarações (opcional).The app normalizes or augments the claims (optional).
  4. O aplicativo usa as declarações para tomar decisões sobre a autorização.The app uses the claims to make authorization decisions.

No OpenID Connect, o conjunto de declarações que você obtém é controlado pelo parâmetro de escopo da solicitação de autenticação.In OpenID Connect, the set of claims that you get is controlled by the scope parameter of the authentication request. No entanto, o Azure AD emite um conjunto limitado de declarações por meio do OpenID Connect; consulte Tipos de declaração e token com suporte.However, Azure AD issues a limited set of claims through OpenID Connect; see Supported Token and Claim Types. Se você quiser mais informações sobre o usuário, será preciso usar a API do Graph do Microsoft Azure AD.If you want more information about the user, you'll need to use the Azure AD Graph API.

Aqui estão algumas das declarações do Azure AD com as quais um aplicativo geralmente se preocupa:Here are some of the claims from Azure AD that an app might typically care about:

Tipo de declaração no token de IDClaim type in ID token DescriçãoDescription
audaud A pessoa para quem o token foi emitido.Who the token was issued for. Essa será a ID de cliente do aplicativo.This will be the application's client ID. Em geral, você não deve se preocupar com essa declaração, pois o middleware a valida automaticamente.Generally, you shouldn't need to worry about this claim, because the middleware automatically validates it. Exemplo: "91464657-d17a-4327-91f3-2ed99386406f"Example: "91464657-d17a-4327-91f3-2ed99386406f"
de recursosgroups Uma lista de grupos do Azure AD dos quais o usuário é membro.A list of Azure AD groups of which the user is a member. Exemplo: ["93e8f556-8661-4955-87b6-890bc043c30f", "fc781505-18ef-4a31-a7d5-7d931d7b857e"]Example: ["93e8f556-8661-4955-87b6-890bc043c30f", "fc781505-18ef-4a31-a7d5-7d931d7b857e"]
ississ O emissor do token OIDC.The issuer of the OIDC token. Exemplo: https://sts.windows.net/b9bd2162-77ac-4fb2-8254-5c36e9c0a9c4/Example: https://sts.windows.net/b9bd2162-77ac-4fb2-8254-5c36e9c0a9c4/
Nomename O nome de exibição do usuário.The user's display name. Exemplo: "Alice A."Example: "Alice A."
oidoid O identificador de objeto para o usuário no Azure AD.The object identifier for the user in Azure AD. Esse valor é o identificador imutável e não reutilizável do usuário.This value is the immutable and non-reusable identifier of the user. Use esse valor e não o email, como um identificador exclusivo para os usuários, pois endereços de email podem mudar.Use this value, not email, as a unique identifier for users; email addresses can change. Se você usar a API do Graph do Microsoft Azure AD no seu aplicativo, a ID de objeto é o valor usado para consultar informações do perfil.If you use the Azure AD Graph API in your app, object ID is that value used to query profile information. Exemplo: "59f9d2dc-995a-4ddf-915e-b3bb314a7fa4"Example: "59f9d2dc-995a-4ddf-915e-b3bb314a7fa4"
rolesroles Uma lista de funções de aplicativo para o usuário.A list of app roles for the user. Exemplo: ["SurveyCreator"]Example: ["SurveyCreator"]
tidtid ID do locatário.Tenant ID. Esse valor é um identificador exclusivo do locatário no Azure AD.This value is a unique identifier for the tenant in Azure AD. Exemplo: "b9bd2162-77ac-4fb2-8254-5c36e9c0a9c4"Example: "b9bd2162-77ac-4fb2-8254-5c36e9c0a9c4"
unique_nameunique_name Um nome de exibição do usuário que pode ser lido por humanos.A human readable display name of the user. Exemplo: "alice@contoso.com"Example: "alice@contoso.com"
upnupn Nome do usuário principal.User principal name. Exemplo: "alice@contoso.com"Example: "alice@contoso.com"

Essa tabela lista os tipos de declaração que aparecem no token de ID.This table lists the claim types as they appear in the ID token. No ASP.NET Core, o middleware do OpenID Connect converte alguns dos tipos de declaração quando popula a coleção Declarações do usuário principal:In ASP.NET Core, the OpenID Connect middleware converts some of the claim types when it populates the Claims collection for the user principal:

  • oid > http://schemas.microsoft.com/identity/claims/objectidentifieroid > http://schemas.microsoft.com/identity/claims/objectidentifier
  • tid > http://schemas.microsoft.com/identity/claims/tenantidtid > http://schemas.microsoft.com/identity/claims/tenantid
  • unique_name > http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameunique_name > http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
  • upn > http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upnupn > http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn

Transformações de declaraçõesClaims transformations

Durante o fluxo de autenticação, talvez você queira modificar as declarações obtidas do IDP.During the authentication flow, you might want to modify the claims that you get from the IDP. No ASP.NET Core, você pode executar a transformação de declarações dentro do evento AuthenticationValidated no middleware do OpenID Connect.In ASP.NET Core, you can perform claims transformation inside of the AuthenticationValidated event from the OpenID Connect middleware. (Confira Eventos de autenticação.)(See Authentication events.)

As declarações que você adicionar durante AuthenticationValidated serão armazenadas no cookie de autenticação de sessão.Any claims that you add during AuthenticationValidated are stored in the session authentication cookie. Elas não serão enviadas por push de volta ao Azure AD.They don't get pushed back to Azure AD.

Veja alguns exemplos de transformação de declarações:Here are some examples of claims transformation:

  • Normalização de declarações normalizaçãoou uniformizar as declarações entre os usuários.Claims normalization, or making claims consistent across users. Isso é especialmente relevante se você estiver obtendo declarações de vários IDPs que podem usar tipos de declaração diferentes para informações semelhantes.This is particularly relevant if you are getting claims from multiple IDPs, which might use different claim types for similar information. Por exemplo, o Azure AD envia uma declaração "upn" que contém o email do usuário.For example, Azure AD sends a "upn" claim that contains the user's email. Outros IDPs podem enviar uma declaração "email".Other IDPs might send an "email" claim. O código abaixo converte a declaração "upn" em uma declaração "email":The following code converts the "upn" claim into an "email" claim:

    var email = principal.FindFirst(ClaimTypes.Upn)?.Value;
    if (!string.IsNullOrWhiteSpace(email))
    {
        identity.AddClaim(new Claim(ClaimTypes.Email, email));
    }
    
  • Adicione valores de declaração padrão para declarações que não estão presentes — por exemplo, atribuir um usuário a uma função padrão.Add default claim values for claims that aren't present — for example, assigning a user to a default role. Em alguns casos, isso pode simplificar a lógica da autorização.In some cases this can simplify authorization logic.

  • Adicione tipos de declaração personalizada com informações específicas do aplicativo sobre o usuário.Add custom claim types with application-specific information about the user. Por exemplo, você pode armazenar informações sobre o usuário em um banco de dados.For example, you might store some information about the user in a database. Você poderia adicionar uma declaração personalizada com essas informações ao tíquete de autenticação.You could add a custom claim with this information to the authentication ticket. A declaração é armazenada em um cookie, por isso basta obtê-la no banco de dados uma vez por sessão de logon.The claim is stored in a cookie, so you only need to get it from the database once per login session. Por outro lado, também é recomendável evitar a criação de cookies excessivamente grandes, portanto você precisa considerar o equilíbrio entre o tamanho do cookie e as pesquisas de banco de dados.On the other hand, you also want to avoid creating excessively large cookies, so you need to consider the trade-off between cookie size versus database lookups.

Depois que o fluxo de autenticação for concluído, as declarações estarão disponíveis em HttpContext.User.After the authentication flow is complete, the claims are available in HttpContext.User. Nesse ponto, você deve tratá-los como uma coleção somente leitura—por exemplo, usando-os para tomar decisões de autorização.At that point, you should treat them as a read-only collection—for example, using them to make authorization decisions.

Validação do emissorIssuer validation

No OpenID Connect, a declaração do emissor ("iss") identifica o IDP que emitiu o token de ID.In OpenID Connect, the issuer claim ("iss") identifies the IDP that issued the ID token. Parte do fluxo de autenticação OIDC serve para verificar se a declaração do emissor corresponde ao emissor verdadeiro.Part of the OIDC authentication flow is to verify that the issuer claim matches the actual issuer. O middleware OIDC lida com isso para você.The OIDC middleware handles this for you.

No Azure AD, o valor de emissor é exclusivo por locatário do AD (https://sts.windows.net/<tenantID>).In Azure AD, the issuer value is unique per AD tenant (https://sts.windows.net/<tenantID>). Portanto, o aplicativo deve fazer uma verificação adicional para ter certeza de que o emissor representa um locatário que tem permissão para entrar no aplicativo.Therefore, an application should do an additional check, to make sure the issuer represents a tenant that is allowed to sign in to the app.

Para um aplicativo de locatário único, você pode apenas verificar se o emissor é seu próprio locatário.For a single-tenant application, you can just check that the issuer is your own tenant. Na verdade, o middleware OIDC faz isso automaticamente por padrão.In fact, the OIDC middleware does this automatically by default. Em um aplicativo multilocatário, você precisa permitir vários emissores, correspondentes aos diferentes locatários.In a multitenant app, you need to allow for multiple issuers, corresponding to the different tenants. Veja uma abordagem geral que pode ser usada:Here is a general approach to use:

  • Nas opções de middleware OIDC, defina ValidateIssuer como false.In the OIDC middleware options, set ValidateIssuer to false. Isso desliga a verificação automática.This turns off the automatic check.
  • Quando um locatário se inscrever, armazene o locatário e o emissor em seu banco de dados do usuário.When a tenant signs up, store the tenant and the issuer in your user DB.
  • Sempre que um usuário fizer logon, pesquise o emissor no banco de dados.Whenever a user signs in, look up the issuer in the database. Se o emissor não for encontrado, significa que o locatário ainda não se inscreveu.If the issuer isn't found, it means that tenant hasn't signed up. Você pode redirecioná-lo para uma página de inscrição.You can redirect them to a sign up page.
  • Você também pode colocar determinados locatários na lista negra, por exemplo, clientes que não pagaram suas assinaturas.You could also blacklist certain tenants; for example, for customers that didn't pay their subscription.

Para obter uma discussão mais detalhada, consulte inscrição e integração de locatário em um aplicativo multilocatário.For a more detailed discussion, see Sign-up and tenant onboarding in a multitenant application.

Usando declarações para autorizaçãoUsing claims for authorization

Com declarações, a identidade de um usuário não é uma entidade monolítica.With claims, a user's identity is no longer a monolithic entity. Por exemplo, um usuário pode ter um endereço de email, número de telefone, aniversário, sexo, etc. Talvez o IDP do usuário armazene todas essas informações.For example, a user might have an email address, phone number, birthday, gender, etc. Maybe the user's IDP stores all of this information. Porém, ao autenticar o usuário, você normalmente obtém um subconjunto dessas declarações.But when you authenticate the user, you'll typically get a subset of these as claims. Neste modelo, a identidade do usuário é simplesmente um pacote de declarações.In this model, the user's identity is simply a bundle of claims. Ao tomar decisões de autorização sobre um usuário, você procura por determinados conjuntos de declarações.When you make authorization decisions about a user, you will look for particular sets of claims. Em outras palavras, a pergunta “O usuário X pode executar a ação Y?” se torna “O usuário X tem a declaração Z?”.In other words, the question "Can user X perform action Y" ultimately becomes "Does user X have claim Z".

Veja alguns padrões básicos para verificar declarações.Here are some basic patterns for checking claims.

  • Para verificar se o usuário tem uma declaração específica com um valor específico:To check that the user has a particular claim with a particular value:

    if (User.HasClaim(ClaimTypes.Role, "Admin")) { ... }
    

    Esse código verifica se o usuário tem uma declaração Função com o valor "Admin".This code checks whether the user has a Role claim with the value "Admin". Ele aborda corretamente o caso de usuários que não tenham a declaração Função ou tenham várias declarações Função.It correctly handles the case where the user has no Role claim or multiple Role claims.

    A classe ClaimTypes define constantes para tipos de declaração usados com frequência.The ClaimTypes class defines constants for commonly used claim types. No entanto, você pode usar qualquer valor da cadeia de caracteres para o tipo de declaração.However, you can use any string value for the claim type.

  • Para obter um único valor de um tipo de declaração, quando você espera que haja no máximo um valor:To get a single value for a claim type, when you expect there to be at most one value:

    string email = User.FindFirst(ClaimTypes.Email)?.Value;
    
  • Para obter todos os valores de um tipo de declaração:To get all the values for a claim type:

    IEnumerable<Claim> groups = User.FindAll("groups");
    

Para obter mais informações, consulte autorização baseada em funções e recursos em aplicativos multilocatários.For more information, see Role-based and resource-based authorization in multitenant applications.

AvançarNext