Série de Autenticação (Parte 1): Práticas de Engenharia de Aplicação
March 8, 2024
Introdução
A autenticação de identidade desempenha um papel crucial na proteção do acesso a dados e na privacidade do usuário em aplicações da internet, especialmente para aplicações internas de empresas. Nesta série de artigos, exploraremos a autenticação de identidade sob diferentes perspectivas, com um foco específico nas práticas de autenticação de identidade na engenharia de aplicações neste artigo.
Em várias aplicações, a autenticação de identidade comumente emprega as seguintes duas técnicas:
-
Cookie & Session: Este mecanismo tradicional de autenticação é amplamente utilizado em aplicações web, principalmente em navegadores. Ele verifica a identidade do usuário e mantém o estado da sessão usando cookies e sessões.
-
Bearer Token: Este é um mecanismo de autenticação mais moderno que elimina a dependência de cookies de navegador e, em vez disso, utiliza o protocolo HTTP para autenticação. É particularmente adequado para cenários de API e pode ser usado em aplicações móveis.
Independentemente do método escolhido, os desenvolvedores precisam selecionar a abordagem de autenticação apropriada para seus produtos para garantir a segurança dos dados, a privacidade do usuário e uma experiência de usuário perfeita.
Aplicações Web Tradicionais
No passado, usávamos Java JSP para construir diretamente aplicações web, identificando usuários usando JSESSIONID, um ID de sessão armazenado em um cookie no navegador do cliente e enviado com cada solicitação.
No entanto, essa abordagem tinha certos problemas. Como os cookies são gerenciados e armazenados no dispositivo do cliente pelo navegador, atacantes maliciosos poderiam roubar o ID de sessão armazenado e se passar pelo usuário, representando um risco de segurança. Além disso, os desenvolvedores às vezes tinham dificuldade em definir períodos de expiração e requisitos de segurança razoáveis para cookies e sessões.
Ao desenvolver essas aplicações, os desenvolvedores frequentemente tinham que implementar a autenticação separadamente para cada sistema, que era independente e usava diferentes sistemas de identidade. Isso exigia trabalho repetitivo. Nesses casos, o Single Sign-On (SSO) poderia resolver esses desafios utilizando um sistema de autenticação unificado, exigindo um trabalho mínimo de integração em cada aplicação web individual para alcançar a funcionalidade de autenticação.
Nos últimos anos, tanto as tecnologias de front-end quanto de back-end fizeram progressos rápidos. Os desenvolvedores começaram a migrar para pilhas de tecnologia mais modernas, deixando aplicações alimentadas por tecnologias desatualizadas como plataformas legadas. No entanto, há casos em que novos requisitos de segurança de identidade surgem, mas modificar o código antigo não é viável. Nesses casos, uma abordagem alternativa é usar um middleware funcionando como um proxy reverso para realizar a autenticação. Antes que o cliente alcance a aplicação, o middleware redireciona o usuário para uma interface de autenticação externa, onde o usuário faz login. O middleware então obtém as informações de identidade do usuário e as anexa à solicitação antes de passá-la para a aplicação antiga. Isso permite que os desenvolvedores adicionem novos mecanismos de autenticação a aplicações antigas sem modificar o código existente.
Evolução das Aplicações Web: Separação do Front-End do Back-End
Com o surgimento de novas tecnologias de front-end, como Vue e React, as interações web foram revolucionadas. No passado, os usuários tinham que preencher e enviar formulários em páginas web, interagindo com o back-end usando formulários HTML e botões, o que não proporcionava uma experiência de usuário suave. Agora, as interações na página são em tempo real, e os desenvolvedores usam scripts JavaScript para interagir com APIs de back-end, oferecendo uma experiência mais consistente e contínua. As interações do usuário mudaram de solicitações HTTP diretas para a invocação de várias APIs.
Há algumas diferenças nos mecanismos de autenticação de identidade entre aplicações voltadas para páginas web e aplicações voltadas para APIs. Embora os cookies antigos ainda possam ser usados, eles não são adequados para tecnologias de front-end modernas. Novas tecnologias capacitam os desenvolvedores com código mais expressivo, permitindo que realizem mais operações, incluindo cenários em que podemos precisar alternar contas de usuário no front-end. No entanto, implementar isso diretamente no front-end por meio de cookies é desafiador (por razões de segurança, cookies relacionados à identidade do usuário são frequentemente configurados como httpOnly, impedindo que scripts JavaScript os leiam e manipulem).
Normalmente, aplicações de front-end modernas gerenciam as sessões do usuário por conta própria. Uma vez que um usuário faz login com sucesso, o front-end gerencia o token gerado pelo back-end e o adiciona ao cabeçalho da solicitação ao fazer chamadas de API para o back-end identificar a identidade do usuário. As APIs usam tokens para identificar informações do usuário. Há vários meios técnicos disponíveis, como implementar manualmente mecanismos de token usando JSON Web Tokens (JWT). O payload do JWT armazena informações de identificação, como o ID do usuário, que é então assinado para permitir que o back-end verifique o token e recupere as informações de identidade do usuário.
No entanto, o JWT também tem algumas desvantagens, como:
-
O tempo de expiração do JWT é fixo e não pode ser modificado uma vez que a assinatura é concluída. Como normalmente não é armazenado pelo back-end e apenas passa por verificação de assinatura, não é possível revogar o token, o que representa um risco de roubo de token.
-
Os dados do payload são armazenados em texto claro e podem ser analisados pelo cliente, tornando-os inadequados para armazenar informações confidenciais.
Felizmente, agora há novas especificações de JWT para abordar essas deficiências. O payload do JWT pode incluir um campo chamado "jti" para armazenar um identificador único para o JWT, que pode ser armazenado no cache do back-end para controlar o ciclo de vida do JWT. Além disso, a especificação JSON Web Encryption (JWE) define uma extensão de JWT criptografado que combina as vantagens da criptografia assimétrica e simétrica, garantindo que o payload seja transmitido em forma de texto cifrado para evitar vazamentos.
Além disso, há outras tecnologias baseadas em JWT que fornecem soluções mais maduras, como OpenID Connect. É importante notar que o OpenID Connect não depende do JWT, mas eles podem ser usados juntos. O OpenID Connect padroniza os mecanismos para tokens de acesso e tokens de atualização, permitindo que os desenvolvedores usem tokens de curta duração para mitigar o risco de roubo de token. O ecossistema do OpenID Connect também está prosperando, com muitas implementações de servidor e cliente disponíveis para ajudar os desenvolvedores a construir sistemas de autenticação de identidade baseados no protocolo OpenID Connect. Além disso, soluções de autenticação de identidade de código aberto, como Keycloak, podem ajudar os desenvolvedores a implementar serviços de autenticação de identidade seguros.
Novas práticas de tecnologia de front-end, como Next.js, estão gradualmente introduzindo técnicas de renderização do lado do servidor no domínio do front-end. Isso representa uma nova evolução do antigo paradigma de desenvolvimento web, combinando React com programas de back-end para aprimorar ainda mais a experiência do usuário. Agora há mais bibliotecas, como NextAuth, que podem ajudar os desenvolvedores a implementar autenticação de identidade usando esse mecanismo, tornando o processo de autenticação mais amigável para o desenvolvedor.
Gateways de API e Autenticação de Identidade
Vamos considerar como nossas aplicações móveis interagem com os dados. Elas também usam APIs? Em aplicações móveis, não há um mecanismo de cookie como em navegadores para armazenar sessões de usuário, então elas usam principalmente tokens para passar informações por meio de cabeçalhos de solicitação HTTP.
E os serviços de API? Um back-end de aplicação bem-sucedido normalmente consiste em muitos sistemas de API complexos que exigem um mecanismo de autenticação de identidade unificado. Caso contrário, os desenvolvedores teriam que implementar o mesmo mecanismo de autenticação para cada serviço, o que seria trabalhoso.
Gateways de API podem nos ajudar a resolver esse problema, lidando com tarefas de autenticação e análise semelhantes a cookies ou tokens, e passando diretamente as informações de identidade analisadas para os serviços de back-end, reduzindo a duplicação de trabalho. Apache APISIX e API7 Enterprise também suportam funcionalidade de autenticação OpenID Connect pronta para uso, ajudando os usuários a integrar serviços de autenticação de identidade diretamente. Além disso, gateways de API suportam a implementação de qualquer mecanismo de autenticação por meio de scripts, então mesmo com mecanismos de autenticação de identidade personalizados, eles podem ser integrados no gateway de API, simplificando o desenvolvimento de aplicações.
Resumo
O desenvolvimento dos métodos de interação do usuário impulsionou avanços na autenticação de identidade. A abordagem centrada em API está se tornando uma tendência dominante, e as APIs podem ser fornecidas por arquiteturas de microsserviços, exigindo um mecanismo de autenticação de identidade unificado para reduzir o desenvolvimento redundante. Portanto, devemos escolher mecanismos mais modernos, como OpenID Connect e JWT, e usar um gateway de API pode fornecer funcionalidade adicional para o desenvolvimento de APIs.