- JWT é a sigla de JSON Web Tokens e é um padrão para tokens autenticados.
- Um JWT é composto por cabeçalho, payload e assinatura ou código de autenticação de mensagem.
- Quem possui a chave de verificação pode confirmar a autenticidade do payload.
Padrão de uso comum do JWT
- O JWT inclui informações como emissor, destinatário, assunto e tempo de expiração.
- Após verificar a autenticidade do token, o destinatário confere se ele ainda não expirou e considera o assunto como um usuário autenticado.
Vantagens do JWT
- A principal vantagem do JWT é que o destinatário pode verificar a autenticidade do token sem se conectar ao banco de dados de usuários.
- Em ambientes de implantação em larga escala, o serviço de autenticação pode ser o único serviço com acesso ao banco de dados central de usuários.
Problemas de logout e invalidação de sessão
- A vida útil do token de autenticação deve ser curta. Por exemplo, no máximo 5 minutos.
- O cliente também recebe um refresh token que pode ser usado para solicitar um novo token de autenticação.
- Na prática, o refresh token acaba funcionando como o verdadeiro token de sessão.
Quando o JWT não é necessário
- Para implementar logout, é preciso manter uma lista de permissões de JWTs válidos ou uma lista de bloqueio de JWTs revogados.
- Para bloquear um usuário, é necessário verificar no banco de dados a flag de "usuário ativo".
- São necessários relacionamentos adicionais entre o objeto do usuário e outros objetos.
- São realizadas operações relacionadas ao banco de dados.
Conclusão
- Se ao menos uma das condições acima se aplicar, você não precisa de JWT.
- É melhor usar um token de sessão opaco comum e armazená-lo no banco de dados.
- Assim, é possível evitar as desvantagens do JWT e reduzir a complexidade.
Opinião do GN⁺
- JWT é adequado para serviços de grande escala, mas pode introduzir complexidade excessiva para a maioria dos serviços pequenos.
- Mecanismos tradicionais de gerenciamento de sessão são suficientes para a maioria das aplicações web.
- Ao usar JWT, pode haver dificuldade para implementar recursos como logout e invalidação de sessão.
- Para aproveitar as vantagens do JWT, é preciso considerar com cuidado a escala e os requisitos do serviço.
- Como alternativa, vale considerar frameworks de autenticação como OAuth2.
8 comentários
Houve muitos benefícios em usar JWT quando era necessária a autenticação de diversos clientes.
No entanto, como escalabilidade e segurança sempre apontam para direções diferentes, se a segurança for especialmente importante, acho melhor usar outro método.
Pessoalmente, acho que tokens JWT devem ser usados quando se trocam, via navegador, dados temporários entre sistemas e não há problema se eles forem expostos.
Para tokens de autenticação que contêm informações pessoais, acho melhor usar tokens opacos.
Pela minha experiência pessoal, houve vantagens em usar JWT ao criar um MVP.
Por exemplo, se for um serviço que você cria e mantém sozinho, a ideia era reduzir o custo de planejamento causado por solicitações repentinas. Como a relação de dados definida no início acabava mudando completamente um ou dois meses depois, quando o planejamento ainda não estava claro, pelo menos no que dizia respeito a
auth, em vez disso eu estruturava o payload do JWT com campos opcionais e implementava as funcionalidades assim. Dessa forma, mesmo sem o time de planejamento fazer a separação de domínios e de serviços, dava para implementar primeiro no serviço monolítico de um jeito em que só o domínio pudesse ser separado com facilidade e então testar o mercado. (E depois seguir com o processo de separar os serviços. Ou remover, se fosse o caso.)Ainda assim, acho que isso varia conforme o domínio do serviço que se quer criar. Como aquele projeto era, entre os serviços em tempo real, um projeto com alta integração com terceiros... lembro de ter seguido por esse caminho pensando que, ao implementar tudo rápido, se um volume enorme de documentos/linhas começasse a se acumular no banco de dados, o custo de manutenção provavelmente ficaria alto.
Claro, se o foco for construir rápido, acho que o modelo de sessão é melhor. (No começo, como o acoplamento entre vários serviços ainda não é tão forte, também é mais fácil refazer tudo e reconstruir.) E o custo de repasse quando outros membros entram na equipe também é menor.
Na época, cheguei a pensar bastante nisso por um tempo, mas olhando agora em retrospectiva, acho que, independentemente de qual abordagem tivesse sido usada, o impacto no projeto provavelmente não teria sido tão grande.
Pessoalmente, acho que ao usar um API gateway há vantagens em implementar a autenticação com JWT, mas tenho curiosidade sobre quais benefícios o JWT traz em serviços de menor escala. Você está se referindo a casos em que as informações do usuário incluídas no JWT mudam com frequência?
Em linhas gerais, é parecido com o que você disse. Só que, em vez de o próprio modelo de usuário mudar e exigir alterações frequentes de informação, era mais um caso em que informações adicionais eram incluídas de forma opcional quando a adição de uma nova feature ou o uso de ferramentas de terceiros em um novo serviço passava a exigir dados complementares. (Indo um pouco além, também havia uma situação meio ambígua sobre potencialmente separar a unidade de gestão de
authusando algo como um API gateway, ou ter um servidor com função equivalente...)Dando um exemplo um pouco mais concreto: estávamos numa situação em que o serviço A era o principal. Como ainda era um MVP, a tabela de usuários guardava apenas informações de pagamento e se o usuário era autenticado. Aí surgiu uma solicitação para adicionar os serviços B e C, que só podiam ser usados se cada usuário tivesse informações de autenticação diferentes. Entre eles, ainda nem estava decidido se o B entraria dentro do serviço A, e o C poderia até desaparecer, então queriam testá-lo de forma leve. (E a funcionalidade de gerenciamento de plano, nem precisava dizer, teria que ser adicionada para evitar problemas). Além disso, queriam começar oferecendo B e C junto com o serviço A nas páginas do serviço web já existente. Pelas características do serviço em operação, até que se criasse uma tabela de gerenciamento de planos (ou uma tabela genérica relacionada a autenticação) e se implementasse o mapeamento desenhando as relações de domínio por serviço, consultar várias tabelas (ou várias coleções) era inevitável. Numa situação em que houvesse alguém para organizar o projeto, teria sido bom fazer algumas reuniões e extrair com precisão qual era exatamente o problema a resolver e quais eram as features desejadas, mas isso não era garantido. Também não estava claro quando seria possível eliminar essas dívidas. Então, como já havia sinais de que esse tipo de coisa poderia acontecer desde antes do lançamento do serviço A... na configuração inicial, acabamos pensando em seguir por um caminho que economizasse ao máximo o custo de consulta no
authe o custo de manutenção futura, e por isso fomos de JWT. Fora isso, acho que havia muitas outras situações pequenas parecidas.Mas, como mencionei no fim do comentário, na prática parece que teria tido pouco impacto no projeto em si independentemente da forma como fosse implementado. Se tivesse sido feito com sessão, provavelmente teríamos encontrado uma solução do nosso jeito também. Na verdade, o que parece ter sido muito mais fatal foi o fato de os desenvolvedores continuarem expostos a situações em que precisavam assumir trabalho de outras funções ou em que o custo de comunicação acabava se rompendo.
Mesmo que seja adequado para uma arquitetura monolítica, quando alguns serviços começam a ser separados ou quando se chega a um ponto de expansão, o JWT e a lógica baseada em sessão claramente mostram diferenças. Não se trata apenas do procedimento de autenticação; na usabilidade da lógica interna, as técnicas para lidar com a fonte dos dados também acabam sendo diferentes, e não sei bem com base em que critério julgar se o contexto de um serviço pequeno é apropriado. A premissa é que todo serviço necessariamente continuará pequeno? Ou que um serviço grande será difícil de sustentar? Não sei. Ainda assim, acho que os serviços que criamos deveriam ter, pelo menos, uma estrutura mínima que dê suporte a contextos úteis, ainda que não saibamos em que situação eles serão necessários. A premissa de um serviço pequeno parece apenas continuar ficando menor.
Opiniões no Hacker News
Resumo dos comentários do Hacker News