OAuth2 é uma das especificações mais populares para autenticação de API atualmente, embora entender isso possa ser um desafio. Muitos aplicativos hoje são na verdade um front-end para uma série de chamadas de API. As APIs são necessárias para o funcionamento adequado de tais aplicativos, mas se você não as proteger, os agentes mal-intencionados podem exfiltrar dados, DDoS seus servidores ou abusar deles.
OAuth é uma das muitas soluções que você pode usar para proteger suas APIs e outros recursos. Ele permite que os usuários deleguem com segurança o acesso aos recursos sem compartilhar suas credenciais originais. OAuth2 (a versão do OAuth que este artigo abordará) existe desde 2012 como um padrão e é baseado em lições de outros padrões anteriores, incluindo OAuth1 e SAML.
Sendo um padrão, o OAuth se beneficia de muitas pessoas inteligentes trabalhando juntas de forma aberta. Como usuário deste padrão, você ganha todo o seu trabalho duro sem precisar contratá-los! Este trabalho inclui análise de segurança, onde o grupo considera constantemente diferentes vetores de ataque e fraquezas no protocolo e os melhora. Os membros do grupo também trabalham para dar suporte a casos de borda estranhos em escala, interfaces de usuário e conectividade de rede. Se você tiver um caso de uso de autenticação típico, o padrão OAuth quase certamente funcionará para você.
Se você precisar de funcionalidade principal, deverá estar coberto por quase todos os servidores OAuth. Mas se você precisar de funcionalidades especializadas, mesmo que sejam parte de um padrão, revise cuidadosamente a documentação de qualquer solução que esteja considerando.
Embora eu me aprofunde mais em como você realmente usa o OAuth para proteger uma API em seu sistema abaixo, incluindo exemplos de código, não abordarei determinados tópicos neste artigo. Alguns dos tópicos que serão omitidos incluem:
Cada especificação relacionada ao OAuth. Há muitos deles!
Todos os casos extremos que o OAuth e os padrões relacionados podem abordar.
Como usar o OAuth para acessar uma API de terceiros, como o Google. Este é um caso de uso relacionado, mas diferente o suficiente para que não faça sentido cobri-lo.
Ao concluir este artigo, você saberá mais sobre por que pode escolher o OAuth, quando usá-lo e algumas alternativas.
Por que usar OAuth para proteger suas APIs?
Ao usar o OAuth, você terceiriza a autenticação e a autorização do usuário para um provedor de identidade central (IdP). Os usuários entram no IdP e recebem permissões com limite de tempo na forma de um token de acesso. Esse token é apresentado a outros aplicativos, APIs e serviços.
Usar um serviço tão centralizado tem várias vantagens:
Um sistema com PII do usuário pode ser bloqueado e protegido mais facilmente do que muitos sistemas.
Assim como um banco de dados se concentra na retenção de dados com certas garantias, um IdP pode se concentrar na funcionalidade de login e fornecer uma interface bem compreendida.
Como um IdP é o local onde as decisões de autorização e autenticação são executadas, ele se torna um único local central para analisar, habilitar e desabilitar o acesso aos sistemas.
Quando todos os usuários se autenticam no IdP, você pode adicionar facilmente funcionalidades, como federação a outras fontes de identidade ou medidas de segurança, como autenticação multifator. Todos os aplicativos, APIs e serviços que aceitam tokens do IdP se beneficiam de funcionalidades adicionais sem qualquer alteração em seu código.
OAuth, que existe há mais de uma década, é onipresente. Existem clientes OAuth em quase todas as linguagens de programação modernas , e até mesmo em algumas menos modernas, como COBOL . Essa onipresença significa que, ao trabalhar com um servidor OAuth, você pode aproveitar as bibliotecas para realizar a integração rapidamente.
Ele foi estendido várias vezes para casos de uso especializados (chamados de perfis) e novos fluxos de autorização (chamados de concessões). O corpo de padrões por trás do OAuth, o grupo de trabalho OAuth IETF , oferece práticas recomendadas para tecnologias mais recentes, como aplicativos móveis ou dispositivos IoT.
Abaixo, discutirei os principais padrões que você deve conhecer, mas esteja ciente de que nem todo IdP implementa todos os padrões dentro do guarda-chuva OAuth. Exemplos de padrões que podem não ser implementados incluem:
A concessão de dispositivo , que permite executar um fluxo OAuth para um dispositivo com opções limitadas de entrada do usuário.
Cadastro dinâmico de clientes , que permite que os clientes se registrem com um IdP de forma automatizada, sem intervenção humana ou fora de banda.
MTLS , que permite que certificados X.509 mútuos sejam usados para autenticação e para vincular tokens a clientes específicos.
Uma amostra das especificações
OAuth foi construído para ser estendido. Ao contrário das especificações anteriores relacionadas à autenticação, como SAML, que eram monolíticas, grandes e difíceis de implementar, o OAuth pode ser composto e extensível. Até mesmo a especificação principal foi entregue em duas RFCs, RFC 6749 (que cobre os fluxos) e RFC 6750 (que detalha o token).
Abaixo estão breves visões gerais dos padrões básicos, bem como alguns que são úteis em circunstâncias específicas. Você também aprenderá sobre padrões que ainda não estão codificados, mas vale a pena ficar de olho. Se você planeja implementar qualquer um deles, é sempre uma boa ideia mergulhar nos próprios textos RFC.
Padrões principais do OAuth
Esses são os principais padrões OAuth, embora nem todas as implementações precisem usar todos eles.
RFC 6749 e RFC 6750 : Conforme mencionado acima, eles compreendem o coração do OAuth. A primeira abrange os principais fluxos de autorização, chamados de concessões. Este último aborda como o token de acesso, o produto final de uma concessão, deve ser usado quando for um token de portador (na maioria das vezes, será um token de portador). Um token de portador não está vinculado a um cliente específico. Eu gosto de pensar em uma ficha de portador como uma chave de carro: qualquer um que tenha a chave pode ligar o carro. Da mesma forma, qualquer pessoa que possua um token de portador pode ter acesso a recursos protegidos por ele.
A RFC 7519 documenta um formato de token comum, JSON Web Tokens ou JWTs. JWTs são objetos JSON que contêm declarações (o que é sofisticado para “dados, possivelmente com um significado padronizado”) sobre uma entidade para a qual o token foi emitido. Eles geralmente são assinados criptograficamente, o que permite que sejam verificados e confiáveis. Os padrões irmãos definem ainda mais JWTs e funcionalidades relacionadas: RFC 7515 , RFC 7516 , RFC 7517 , RFC 7518 e RFC 7520 . O RFC 7517 é especialmente útil, pois abrange a publicação de chaves públicas, o que permite que algoritmos de assinatura assimétrica, como RSA, sejam usados para assinar um JWT.
O OpenID Connect (OIDC) é uma extensão do OAuth (chamado de perfil) que permite o acesso a informações de autenticação. Embora o OAuth possa e seja usado sem OIDC, eles geralmente são implementados juntos.
A RFC 7662 documenta a introspecção. Esse processo valida um token de acesso comunicando-se com o servidor OAuth que o criou. Usar a introspecção é uma alternativa aos JWTs e outros formatos de token independentes.
A RFC 7636 descreve o PKCE (pronuncia-se ‘pixie’) e é um exemplo de como os padrões tratam de questões de segurança. O PKCE protege clientes incapazes de guardar segredos, como navegadores ou aplicativos móveis, de toda uma classe de ataques. O PKCE é recomendado para todos os clientes que usam a concessão do Código de Autorização.
O documento em evolução das melhores práticas atuais (BCP) de segurança OAuth2.0 discute ameaças de segurança e estende o padrão de modelo de ameaça OAuth de 2013, RFC 6819 , que tem quase uma década.
Em seguida, vejamos alguns padrões interessantes que podem não ser aplicáveis em todas as situações.
Padrões OAuth especializados
Como o OAuth é extensível, algumas funcionalidades opcionais podem ser muito importantes para você e outras não. Não há um repositório central que mostre quais IdPs suportam quais padrões, portanto, verifique a documentação técnica para garantir que você obtenha a implementação e a funcionalidade de que precisa.
Alguns padrões que se enquadram nesta categoria incluem:
A RFC 8252 discute concessões OAuth e aplicativos móveis. Como os aplicativos móveis não podem manter segredos e cada aplicativo tem um alto nível de controle sobre a entrada do usuário, há algumas etapas adicionais que você deve seguir para garantir a segurança. Isso é especialmente importante se o cliente e o IdP não forem controlados pela mesma organização.
RFC 7591 , registro dinâmico de clientes, permite que os clientes se registrem. No núcleo OAuth, o registro do cliente ocorre raramente e normalmente é feito de maneira manual. Com esta RFC, os clientes podem descobrir tudo o que precisam para se cadastrar. Isso é útil quando você deseja ter muitos clientes exclusivos.
A RFC 8628 cria uma concessão adicional, a concessão de dispositivo, projetada especificamente para clientes que têm opções limitadas de entrada do usuário, como televisores ou outros dispositivos. Com essa concessão, as pessoas podem fazer login usando um dispositivo de entrada secundário, como um computador ou telefone, e ainda fazer com que o cliente original receba o token de acesso.
A RFC 9068 aborda como especificar tokens de acesso JWT em um formato padrão, permitindo que diferentes IdPs e servidores de recursos interoperem.
O DPoP / MTLS aborda um problema não resolvido com o token principal RFC, 6750, devido à complexidade da implementação. Esses documentos (o primeiro deles é um rascunho, não uma RFC completa) descrevem como vincular um token a um cliente específico. Cada um deles usa um mecanismo diferente, mas se a ideia de um token de portador ser roubado e usado por um agente mal-intencionado for inaceitável para você ou sua equipe de segurança, usá-los pode ajudar.
OAuth continua a evoluir e há dois esforços principais para melhorá-lo. Vamos discutir esses esforços na próxima seção.
O futuro do OAuth
Embora existam muitas melhorias incrementais sendo discutidas em vários órgãos de padrões, os dois principais esforços para melhorar o núcleo do OAuth são OAuth 2.1 e GNAP.
OAuth 2.1 está atualmente em desenvolvimento ativo. Essa especificação consolida as práticas recomendadas de segurança e usabilidade que foram adicionadas ao OAuth ao longo dos anos desde que foi lançado. Os autores excluíram explicitamente quaisquer mudanças ou modificações radicais.
O GNAP, por outro lado, é uma releitura do protocolo OAuth, da mesma forma que o OAuth2 foi uma releitura de protocolos anteriores. Esse rascunho inicial inclui alterações importantes, como a introdução de novos atores de software e a alteração do formato de comunicação principal de parâmetros de formulário para JSON.
Ufa, foi muito. Espero que isso lhe dê uma ideia da amplitude do cenário OAuth, bem como dos tipos de problemas que você pode resolver usando-o.
A seguir, vamos nos aprofundar em alguns detalhes.
Gerenciando recursos
Considere um aplicativo simples, diagramado acima, que permite aos usuários gerenciar todos. Clientes como um navegador da web ou aplicativo móvel acessarão dois componentes diferentes: uma plataforma OAuth para autenticar usuários e uma API Todo para adicionar, atualizar ou excluir todos.
Uma concessão OAuth é um fluxo específico que resulta em um token de acesso. De acordo com a especificação, um token é uma string opaca sem qualquer estrutura. No entanto, os servidores OAuth podem escolher seu formato de token e muitos usam JSON Web Tokens, que possuem estrutura interna. Algumas partes da concessão, como mensagens de erro ou parâmetros esperados, são bem definidas. Outros, como o processo de autenticação real, são deixados como detalhes de implementação.
Uma concessão autentica o usuário ou outra entidade, reúne as permissões apropriadas com base nas funções do usuário, grupos e escopos solicitados, reúne os dados de autorização e encapsula essas permissões do servidor de autorização na forma de um token de acesso. Aqui está um exemplo de um token: mF_9.B5f-4.1JqM.
O token é frequentemente, mas nem sempre, enviado ao cliente para apresentação posterior ao servidor de recursos. No diagrama acima, os aplicativos móveis e o navegador à esquerda passarão por uma concessão OAuth para obter acesso à API Todo.
Nesse contexto, qual subsídio você deve escolher para enviar seus usuários? O núcleo RFC, RFC 6749, define uma série de concessões. Pode ser confuso determinar qual é o melhor ajuste para o seu caso de uso.
Para a maioria dos desenvolvedores, existem apenas algumas perguntas a serem feitas:
Há um ser humano envolvido?
Por quanto tempo o cliente precisará de acesso ao recurso protegido?
Vamos abordar cada questão.
Sempre que um usuário estiver envolvido, a melhor concessão a ser usada é a concessão do Código de Autorização. Esta concessão será discutida em mais detalhes abaixo. O uso disso oferece flexibilidade arquitetônica em torno da localização final do token de acesso, bem como um melhor perfil de segurança. Em geral, você deve emparelhar a concessão do Código de Autorização com o PKCE.
No aplicativo todo descrito no diagrama acima, um ser humano está fazendo a solicitação inicial para exibir todos em seu aplicativo, portanto, a concessão do Código de Autorização deve ser usada.
Mas vamos considerar uma situação diferente.
Suponha que estendamos o aplicativo com novas funcionalidades para lembrar nossos usuários dos prazos associados às suas pendências.
Nesse caso, precisamos de um serviço de lembrete que funcione todos os dias, veja quais pendências estão atrasadas e envie um e-mail de lembrete. Esse serviço ainda precisaria ser autenticado porque não gostaríamos que ninguém pudesse acessar nossos todos. Mas não há usuário iniciando a solicitação – talvez seja apenas um cron job.
Esse fluxo de permissões pode ser mais ou menos assim:
Quando não há um ser humano iniciando a solicitação, a concessão correta a ser usada é a concessão de credenciais do cliente . Essa concessão deve ser usada sempre que você tiver comunicação serviço a serviço e quiser aproveitar o suporte à biblioteca de cliente, autenticação centralizada e infraestrutura de segurança de um servidor de autorização.
Por quanto tempo o cliente precisará de acesso ao recurso protegido?
Em geral, os tokens de acesso são bons por um curto período de tempo (segundos a minutos). Se o cliente puder obter acesso aos recursos de que precisa nesse momento, tudo estará bem. No entanto, às vezes o cliente precisa de acesso a longo prazo. Quando o token de acesso expira, o cliente pode solicitar que o usuário se autentique novamente ou pode usar a concessão Atualizar.
Essa concessão permite que um cliente solicite novamente de forma transparente um token com as mesmas permissões sem forçar o usuário a se autenticar novamente.
E as outros recursos?
As outras concessões, como a concessão de dispositivo ou a concessão de senha do proprietário do recurso, devem ser usadas somente quando o caso de uso solicitar sua funcionalidade específica.
Em geral, use a concessão de Código de Autorização se houver um ser humano envolvido e a concessão de Credenciais de Cliente se estiver realizando comunicação de servidor para servidor.
Alternativas ao OAuth
OAuth não é a única opção para proteger sua API. A principal alternativa são as chaves de API. Eles são uma boa solução em algumas situações e são simples de entender. No entanto, em comparação com o OAuth, eles apresentam algumas deficiências.
As chaves de API são relativamente estáticas. Embora você possa e deva alternar as chaves de API, você precisa criar a infraestrutura para fazer isso sozinho. As chaves de API não são limitadas no tempo, a menos que você também construa isso em seu sistema.
As chaves de API são “segredos” e devem ser gerenciadas como tal. Assim como o segredo do cliente OAuth, as chaves de API são dados privilegiados, o que significa que você não pode, por exemplo, armazená-las com segurança em JavaScript. Portanto, eles limitam sua flexibilidade arquitetônica.
Também não há informações codificadas em uma chave de API, ao contrário dos tokens, que podem ter informações codificadas, especialmente se um token de acesso for um JWT. Esse formato de dados mais rico pode incluir informações úteis específicas de negócios, como um nível de assinatura do aplicativo de tarefas. Também permite que a autorização seja realizada sem a necessidade de “ligar para casa” para o servidor OAuth que criou o token.
Conclusão
Neste artigo, você aprendeu por que o OAuth é uma boa opção para proteger o acesso às suas APIs, mais sobre seus padrões de componentes e opções para usar concessões OAuth para proteger recursos. Você também aprendeu sobre alternativas ao uso do OAuth, como chaves de API.
Embora o OAuth possa ser complexo, ele lida com um grande número de casos de uso. Você separa a preocupação da autenticação para um componente especializado, enquanto usa uma credencial temporária padronizada (o token) no resto do seu sistema. Além disso, ao usar o OAuth, você aproveita padrões e conhecimentos de todo o mundo.