Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Por Damien Bowden
A autenticação JWT (JSON Web Token) do tipo Bearer é frequentemente utilizada para APIs. Embora opere de forma semelhante à autenticação cookie, o provedor de identidade emite um JWT ou tokens após uma autenticação bem-sucedida. Esses tokens podem ser enviados para outros servidores para autenticação, ao contrário dos cookies que só são enviados de volta para o domínio emissor. Um JWT é um token autônomo que encapsula informações para um recurso de API ou um cliente. O cliente que solicitou o JWT pode solicitar dados de um recurso de API usando o cabeçalho Authorization e um token de portador.
A autenticação por portador JWT fornece:
-
Autenticação: Ao usar o
JwtBearerHandlertokens de portador, são essenciais para a autenticação. OJwtBearerHandlervalida o token e extrai a identidade do usuário de suas declarações. - Autorização: Tokens portadores permitem a autorização fornecendo uma coleção de declarações que representam as permissões do usuário ou da aplicação, muito parecido com um cookie.
- de Autorização Delegada: Quando um token de acesso específico do usuário é usado para autenticar entre APIs em vez de um token de acesso em todo o aplicativo, esse processo é conhecido como de autorização delegada.
Para obter uma introdução à autenticação de portador JWT, consulte JSON Web Tokens.Ver ou transferir código de exemplo
Este artigo abrange as seguintes áreas:
- Tipos de token
- Usando tokens JWT para proteger uma API
- Como o OIDC/OAuth se encaixa nisso?
- Implementando a autenticação com token JWT
- Abordagens recomendadas para criar um JWT
Tipos de token
Existem inúmeros tipos de tokens e formatos. Gerar seus próprios tokens de acesso ou tokens de ID é desencorajado, exceto para fins de teste. Tokens autocriados que não aderem aos padrões estabelecidos:
- Pode levar a vulnerabilidades de segurança.
- São adequados apenas para sistemas fechados.
Recomendamos o uso OpenID Connect 1.0 ou um padrão OAuth para criar tokens de acesso destinados ao acesso à API.
Tokens de acesso
Tokens de acesso:
- São cadeias de caracteres usadas por um aplicativo cliente para fazer solicitações ao servidor que implementa uma API.
- Pode variar no formato. APIs diferentes podem usar formatos diferentes para os tokens.
- Pode ser encriptado.
- Nunca deve ser lido ou interpretado por um cliente Web ou aplicativo de interface do usuário que contém o token de acesso.
- Destinam-se exclusivamente a fazer solicitações para uma API.
- Normalmente, são enviados para a API no cabeçalho da solicitação de autorização como um token de portador.
Consulte a estrutura de autorização do OAuth 2.0
Tokens de acesso a aplicativos e tokens de acesso delegado
Os tokens de acesso podem ser tokens de acesso ao aplicativo ou tokens de acesso delegado. Os tokens têm declarações diferentes e são gerenciados e armazenados de forma diferente. Um token de acesso da aplicação é normalmente armazenado uma vez na aplicação até expirar, enquanto um token de acesso delegado é armazenado por utilizador, num cookie ou num cache de servidor seguro.
Recomendamos o uso de tokens de acesso de usuário delegado sempre que um usuário estiver envolvido. As APIs downstream podem solicitar um token de acesso de usuário delegado em nome do usuário autenticado.
Tokens de acesso com restrições do remetente
Tokens de acesso podem ser usados como tokens de portador ou como tokens restritos pelo remetente para acessar recursos. Os tokens restritos pelo remetente exigem que o cliente solicitante prove a posse de uma chave privada para usar o token. Provar a posse de uma chave privada garante que o token não pode ser usado de forma independente. Os tokens restritos ao remetente podem ser implementados de duas maneiras:
Tokens de identificação
Os tokens de ID são tokens de segurança que confirmam a autenticação bem-sucedida de um usuário. Os tokens permitem que o cliente verifique a identidade do usuário. O servidor de token JWT emite tokens de identificação contendo afirmações com informações do usuário. Os tokens de ID estão sempre no formato JWT
Os tokens de ID nunca devem ser usados para acessar APIs.
Outros tokens
Existem muitos tipos de tokens, incluindo tokens de acesso e ID, conforme especificado pelos padrões OpenID Connect e OAuth. Os tokens de atualização podem ser usados para atualizar um aplicativo de interface do usuário sem autenticar novamente o usuário. Os tokens JAR OAuth podem enviar solicitações de autorização com segurança. Os fluxos de credenciais verificáveis utilizam tipos JWT para emitir ou verificar credenciais. É crucial usar tokens de acordo com as especificações. Consulte os links de padrões fornecidos posteriormente neste artigo para obter mais informações.
Usando tokens JWT para proteger uma API
Ao usar tokens de acesso JWT para autorização de API, a API concede ou nega acesso com base no token fornecido. Se a solicitação não for autorizada, uma resposta 401 ou 403 será retornada. A API não deve redirecionar o usuário para o provedor de identidade para obter um novo token ou solicitar permissões adicionais. O aplicativo que consome a API é responsável por adquirir um token apropriado. Isso garante uma separação clara de preocupações entre a API (autorização) e o aplicativo cliente consumidor (autenticação).
Observação
HTTP também permite retornar 404 para não autorizado, de modo a não vazar informações sobre a existência de recursos para clientes não autorizados.
401 Não autorizado
Uma resposta 401 Não autorizada indica que o token de acesso fornecido não atende aos padrões exigidos. Esta situação pode dever-se a várias razões, incluindo:
- Assinatura inválida: a assinatura do token não corresponde, sugerindo uma possível adulteração.
- Expiração: O token expirou e não é mais válido.
-
Declarações incorretas: declarações críticas dentro do token, como a audiência (
aud) ou o emissor (iss), estão ausentes ou são inválidas.
Observação
A partir da semântica HTTP da RFC 9110 : O servidor que gera uma resposta 401 DEVE enviar um cabeçalho WWW-Authenticate (seção 11.6.1) contendo pelo menos um desafio aplicável ao recurso de destino.
As especificações OAuth fornecem diretrizes detalhadas sobre as declarações necessárias e sua validação.
403 Proibido
Uma resposta 403 Proibido normalmente indica que o usuário autenticado não tem as permissões necessárias para acessar o recurso solicitado. Isso é diferente de problemas de autenticação, por exemplo, um token inválido, e não está relacionado às declarações padrão dentro do token de acesso.
No ASP.NET Core, você pode impor a autorização usando:
Requisitos e políticas: defina requisitos personalizados, por exemplo, "Deve ser um administrador" e associe-os a políticas. Autorização baseada em função: atribua usuários a funções, por exemplo, "Administrador", "Editor" e restrinja o acesso com base nessas funções.
Que papel tem o OIDC e/ou OAuth ao usar tokens de portador?
Quando uma API usa tokens de acesso JWT para autorização, a API apenas valida o token de acesso, não sobre como o token foi obtido.
O OpenID Connect (OIDC) e o OAuth 2.0 fornecem estruturas padronizadas e seguras para aquisição de tokens. A aquisição de tokens varia dependendo do tipo de aplicativo. Devido à complexidade da aquisição segura de tokens, é altamente recomendável confiar nestes padrões:
- Para aplicativos que atuam em nome de um usuário e um aplicativo: o OIDC é a escolha preferida, permitindo o acesso de usuário delegado. Em aplicativos Web, o fluxo de código confidencial com PKCE (Proof Key for Code Exchange ) é recomendado para maior segurança.
- Se o aplicativo de chamada for um aplicativo ASP.NET Core com autenticação OIDC do lado do servidor, você poderá usar a propriedade para armazenar o SaveTokens token de acesso em um cookie para uso posterior via
HttpContext.GetTokenAsync("access_token").
- Se o aplicativo de chamada for um aplicativo ASP.NET Core com autenticação OIDC do lado do servidor, você poderá usar a propriedade para armazenar o SaveTokens token de acesso em um cookie para uso posterior via
- Se o aplicativo não tiver usuário: o fluxo de credenciais do cliente OAuth 2.0 é adequado para obter tokens de acesso ao aplicativo.
Implementando a autenticação com token JWT
O pacote Nuget Microsoft.AspNetCore.Authentication.JwtBearer pode ser usado para validar os tokens de portador JWT.
Os tokens de portador JWT devem ser totalmente validados em uma API. Os seguintes devem ser validados:
- Assinatura, para confiança e integridade. Isso garante que o token foi criado pelo serviço de token seguro designado e não foi adulterado.
- Reclamação do emitente com o valor esperado.
- Estimativa de audiência com o valor esperado.
- Expiração do token.
As seguintes declarações são necessárias para tokens de acesso OAuth 2.0: iss, exp, aud, sub, client_id, iate jti.
Se qualquer uma dessas declarações ou valores estiverem incorretos, a API deverá retornar uma resposta 401.
Validação básica do token portador JWT
Uma implementação básica do AddJwtBearer pode validar apenas o público e o emissor. A assinatura deve ser validada para que o token possa ser confiável e não tenha sido adulterado.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = "https://{--your-authority--}";
jwtOptions.Audience = "https://{--your-audience--}";
});
Validação explícita do token portador JWT
O AddJwtBearer método fornece várias configurações. Alguns provedores de token seguro usam um endereço de metadados não padrão e o parâmetro pode ser configurado explicitamente. A API pode aceitar vários emissores ou públicos.
Não é necessário definir explicitamente os parâmetros. As definições dependem dos valores de declaração do token de acesso e do servidor de token seguro usado para validar o token de acesso. Você deve usar os valores padrão, se possível.
Consulte Mapeamento de Declarações MapInboundClaims.
builder.Services.AddAuthentication()
.AddJwtBearer("some-scheme", jwtOptions =>
{
jwtOptions.MetadataAddress = builder.Configuration["Api:MetadataAddress"];
// Optional if the MetadataAddress is specified
jwtOptions.Authority = builder.Configuration["Api:Authority"];
jwtOptions.Audience = builder.Configuration["Api:Audience"];
jwtOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidAudiences = builder.Configuration.GetSection("Api:ValidAudiences").Get<string[]>(),
ValidIssuers = builder.Configuration.GetSection("Api:ValidIssuers").Get<string[]>()
};
jwtOptions.MapInboundClaims = false;
});
JWT com vários esquemas
As APIs geralmente precisam acomodar tokens de acesso de vários emissores. O suporte a vários emissores de token em uma API pode ser realizado por:
- APIs separadas: crie APIs distintas com esquemas de autenticação dedicados para cada emissor.
- AddPolicyScheme Esse método pode definir vários esquemas de autenticação e implementar lógica para selecionar o esquema apropriado com base nas propriedades do token (por exemplo, emissor, declarações). Essa abordagem permite maior flexibilidade dentro de uma única API.
Forçar a autenticação do portador
SetFallbackPolicy pode ser usado para exigir autenticação para todas as solicitações, mesmo no caso de endpoints sem um atributo [Authorize].
SetDefaultPolicy configura a política usada para terminais com o atributo [Authorize] e já tem como padrão exigir utilizadores autenticados. Consulte a documentação sobre a exigência de utilizadores autenticados para obter mais detalhes.
var requireAuthPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
builder.Services.AddAuthorizationBuilder()
.SetFallbackPolicy(requireAuthPolicy);
O AuthorizeAttribute atributo também pode ser usado para forçar a autenticação. Se forem utilizados vários esquemas, o esquema bearer tem geralmente de ser definido como o esquema de autenticação predefinido ou especificado através de [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme]).
Autorização em controladores
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
Autorização em APIs mínimas:
app.MapGet("/hello", [Authorize] () => "Hi");
Abordagens recomendadas para criar um JWT
O tratamento inseguro de tokens de acesso, como autenticação fraca ou armazenamento de tokens em armazenamento vulnerável do lado do cliente, pode levar a vulnerabilidades de segurança significativas. Por exemplo, armazenar tokens de acesso diretamente no navegador usando armazenamento local, armazenamento de sessão ou web workers. A seção a seguir contém práticas recomendadas para aplicativos que usam e criam tokens de acesso.
Normas de utilização
Padrões como OpenID Connect ou OAuth devem sempre ser usados ao criar tokens de acesso. Os tokens de acesso não devem ser criados em aplicações de produção sem cumprir as precauções de segurança indicadas neste artigo. A criação de tokens de acesso deve ser limitada a cenários de teste.
Usar chaves assimétricas
As chaves assimétricas devem ser sempre usadas ao criar tokens de acesso. A chave pública está disponível nos pontos de extremidade conhecidos e os clientes de API podem validar a assinatura do token de acesso usando a chave pública.
Nunca crie um token de acesso a partir de um pedido de nome de utilizador/palavra-passe
Você NÃO deve criar um token de acesso a partir de uma solicitação de nome de usuário/senha. As solicitações de nome de usuário/senha não são autenticadas e são vulneráveis a ataques de falsificação de identidade e phishing. Os tokens de acesso só devem ser criados usando um fluxo OpenID Connect ou um fluxo padrão OAuth. Desviar-se desses padrões pode resultar em um aplicativo inseguro.
Utilizar cookies
Para aplicativos Web seguros, um back-end é necessário para armazenar tokens de acesso em um servidor confiável. Somente um HTTP apenas seguro cookie é compartilhado no navegador do cliente. Consulte a documentação de autenticação OIDC para saber como fazer isso em um aplicativo Web ASP.NET Core.
APIs a jusante
Ocasionalmente, as APIs precisam acessar dados do usuário de APIs downstream em nome do usuário autenticado no aplicativo de chamada. Embora a implementação de um fluxo de credenciais de cliente OAuth seja uma opção, ela requer confiança total entre os dois aplicativos de API. Uma abordagem mais segura envolve o uso de uma estratégia de confiança zero com um token de acesso de usuário delegado. Esta abordagem:
- Aumenta a segurança concedendo à API apenas as permissões necessárias para esse usuário específico.
- Requer a API para criar o novo token de acesso para o usuário que chama o aplicativo e a API.
Há várias maneiras de implementar uma estratégia de confiança zero com um token de acesso de usuário delegado:
Use o OAuth 2.0 Token Exchange para solicitar um novo token de acesso delegado
Esta é uma boa maneira de implementar esse requisito, mas é complicado se você precisar implementar o fluxo OAuth.
Consulte OAuth 2.0 Token Exchange
Usar o Microsoft Identity Web em nome do Flow para solicitar um novo token de acesso delegado
Usar a biblioteca de autenticação da Web da Microsoft Identity é a abordagem mais fácil e segura. Só funciona com Microsoft Entra ID, Microsoft Entra External ID.
Para obter mais informações, consulte Microsoft identity platform e OAuth 2.0 On-Behalf-Of flow.
Usar o mesmo token de acesso delegado enviado para a API
Essa abordagem não é difícil de implementar, mas o token de acesso tem acesso a todas as APIs downstream. O proxy reverso Yarp pode ser usado para implementar isso.
Usar o fluxo de credenciais do cliente OAuth e usar um token de acesso ao aplicativo
Isso é fácil de implementar, mas o aplicativo cliente tem acesso total ao aplicativo e não um token de acesso delegado. O token deve ser armazenado em cache no aplicativo de API do cliente.
Observação
Qualquer segurança entre aplicações também funciona. A autenticação de certificado ou, no Azure, uma identidade gerenciada pode ser usada.
Gestão de tokens de acesso
Ao usar tokens de acesso numa aplicação cliente, os tokens de acesso devem ser rotacionados, persistidos e armazenados no servidor. Em um aplicativo da web, os cookies são usados para proteger a sessão e podem ser usados para armazenar tokens através da SaveTokens propriedade.
SaveTokens não atualiza os tokens de acesso automaticamente, mas essa funcionalidade está planejada para uma versão futura. Enquanto isso, tu podes atualizar manualmente o token de acesso conforme demonstrado na documentação do OIDC Blazor Web App ou utilizar um pacote NuGet de terceiros, como Duende.AccessTokenManagement.OpenIdConnect. Para obter mais informações, consulte Gerenciamento de token Duende.
Observação
Se for implantado na produção, o cache deverá funcionar numa implantação de várias instâncias. Normalmente, é necessário um cache persistente.
Alguns servidores de token seguros criptografam os tokens de acesso. Os tokens de acesso não requerem qualquer formato. Ao usar a introspeção OAuth, um token de referência é usado em vez de um token de acesso. Um aplicativo cliente (UI) nunca deve abrir um token de acesso, pois o token de acesso não se destina a isso. Somente uma API para a qual o token de acesso foi criado deve abrir o token de acesso.
- Não abra tokens de acesso em uma aplicação de interface de utilizador
- Não envie o token de ID para as APIs
- Os tokens de acesso podem ter qualquer formato
- Os tokens de acesso podem ser criptografados
- Os tokens de acesso expiram e precisam ser alternados
- Os tokens de acesso são mantidos em um servidor de back-end seguro
YARP (mais um proxy reverso)
YARP (Yet Another Reverse Proxy) é uma tecnologia útil para lidar com solicitações HTTP e encaminhar as solicitações para outras APIs. O YARP pode implementar lógica de segurança para adquirir novas credenciais de acesso. O YARP é frequentemente usado ao adotar a arquitetura de segurança Backend for Frontend (BFF).
Para Blazor obter exemplos que usam YARP para implementar o padrão BFF, consulte os seguintes artigos:
Para obter um Blazor exemplo que usa YARP para implementar o padrão BFF, consulte Proteger um ASP.NET Core Blazor Web App com OpenID Connect (OIDC).
Para obter mais informações, consulte auth0: The Backend for Frontend Pattern.
Testar APIs
Testes de integração e contêineres com tokens de acesso podem ser usados para testar APIs seguras. Os tokens de acesso podem ser criados usando a ferramenta dotnet user-jwts.
Advertência
Certifique-se de que os problemas de segurança não sejam introduzidos na API para fins de teste. O teste se torna mais desafiador quando tokens de acesso delegado são usados, pois esses tokens só podem ser criados por meio de uma interface do usuário e um fluxo OpenID Connect. Se uma ferramenta de teste for usada para criar tokens de acesso delegado, os recursos de segurança deverão ser desabilitados para teste. É essencial que esses recursos sejam desativados apenas no ambiente de teste.
Crie ambientes de teste dedicados e isolados onde os recursos de segurança podem ser desativados ou modificados com segurança. Certifique-se de que essas alterações sejam estritamente limitadas ao ambiente de teste.
Utilize o Swagger UI, Curl e outras interfaces de API UI.
Swagger UI e Curl são ótimas ferramentas de interface do usuário para testar APIs. Para que as ferramentas funcionem, a API pode produzir um documento OpenAPI e isso pode ser carregado na ferramenta de teste do cliente. Um fluxo de segurança para adquirir um novo token de acesso pode ser adicionado ao arquivo API OpenAPI.
Advertência
Não implante fluxos de teste de segurança inseguros na produção.
Ao implementar uma interface do usuário Swagger para uma API, você normalmente não deve implantar a interface do usuário na produção, pois a segurança deve ser enfraquecida para permitir que isso funcione.
Mapear as declarações do OpenID Connect
Consulte o seguinte documento:
Mapeamento, personalização e transformação de declarações no ASP.NET Core
Normas
- JSON Web Token (JWT)
- A estrutura de autorização do OAuth 2.0
- OAuth 2.0 Demonstrando a Prova de Posse DPoP
- OAuth 2.0 JWT-Secured Pedido de Autorização (JAR) RFC 9101
- Autenticação de cliente Mutual-TLS OAuth 2.0 e tokens de acesso Certificate-Bound
- OpenID Connect 1.0
- Plataforma de identidade da Microsoft e fluxo On-Behalf-Of OAuth 2.0
- Troca de tokens OAuth 2.0
- Perfil JSON Web Token (JWT) para tokens de acesso OAuth 2.0
- Semântica HTTP RFC 9110