[Dúvida] [JWT] [Autenticação]

Estou com uma demanda de atualizar nosso método de autenticação para JWT (ou, pelo menos, analisar a viabilidade, comparando-o com a forma atual.

Dentro das pesquisas que fiz, parece que pelo JWT a gente não precisaria ter a persistência das informações de autênticação, bastaria o token, que após a descriptografia nos diz o id do usuário, a data de expiração.

Seria isso mesmo?

Alguém que está utilizando na prática, pode compartilhar qual foi a lógica implementada para garantir a seguraça?

Vou deixar aqui um repositório para você conferir: (https://github.com/wellingtonrodriguesbr/pollify-api/blob/main/src/http/controllers/users/authenticate-controller.ts)

Aqui vai um resumo do funcionamento de tokens:

  • O token expira mais rápido e é usado pelo front-end nos cabeçalhos das requisições (Bearer Token).
  • O refresh token dura mais e é guardado nos cookies do lado do servidor.

No axios por exemplo, usamos os interceptors para interceptar requisições e respostas. Se a resposta falhar devido ao token expirado, a API precisa de uma rota para gerar um novo token usando o refresh token. O axios então tenta a requisição novamente com o novo token, garantindo que dê sucesso. Se ficou muito confuso, pode perguntar novamente que tento ajudar.

Um detalhe importante é que o JWT não faz criptografia por padrão.

Os três segmentos do token na verdade estão apenas encodados em base64, então qualquer pessoa pode ver o que está no payload do token (onde você colocaria a identificação do usuário e outras informações relevantes). A segurança dele vem pelo último segmento que é a assinatura do payload, assim você consegue validar que aquele payload foi gerado por você, já que a chave da criptografia deve ser algo privado que só a sua aplicação conhece.

Este foi um detalhe importante para saber... Então, dados sensíveis, não são interessantes de serem inseridos neste token, né?
Exatamente. Você pode encriptar o conteúdo ou utilizar o JWE (Json Web Encryption) caso seja muito necessário.
no meu caso, para autenticação, estou enviando o user_id e um pass (gerado aleatoriamente e o rash salvo no servidor), que são verificados a cada requisição. acha relevante a criptografia para este caso de uso?
Pelo que li dos outros comentários, esse hash extra só serve pra você fazer mais uma validação de segurança do token, você pode usar isso pra colocar metadados do token no seu banco, como a possibilidade de cancelar esse token quando quiser, por exemplo ao salvar no banco o hash e uma flag de válida ou não, mas se não for usar pra isso, é desnecessário. Ainda me parece que você não entendeu completamente a solução que o JWT traz. Você pode pensar no token gerado como um crachá que você deu pro usuário assim que ele entrou na sua aplicação, contendo o nome dele para que qualquer um possa ler, mas você também adicionou um carimbo que só você tem, então por mais que qualquer um consiga ler o conteúdo, apenas você é capaz de fazer aquele carimbo no crachá. Dessa forma, se você ver o usuário novamente você terá certeza que o nome dele está correto no crachá porque apenas você poderia ter carimbado daquele jeito. Edit: esqueci de responder a sua última pergunta, não, não acho que seja relevante porque o user id não deve ser um dado sensível.
entendido! complementando a analogia, é como se o crachá dado ao usuário fosse feito em um cartão magnético, que, dependendo da sensibilidade do que ele pretende acessar, eu posso gerar mais uma validação. já estou conseguindo entender a utilidade sim... mas para a natureza da aplicação que será trabalhada, é exigido o máximo possível de segurança para alguns endpoints, por isso pensei em mais uma camada de segurança. quanto ao id, realmente não precisa ser considerado sensível...

Olá! Vc consegue colocar algumas (várias) informações dentro do token, na sessão Payload, como nome de usuário, user id, roles, etc. Quanto mais coisa colocar, maior fica.

No https://jwt.io/ vc pode ver mais características de um token.

isso que estou vendo aqui... colocarei mais algumas informações, inclusive as que vou persistir no servidor, oara ter mais uma camada de proteção

parece que pelo JWT a gente não precisaria ter a persistência das informações de autênticação,

Correto, mas isso não é exclusivo do JWT. Os fluxos do OAuth (há vários) já têm isso em mente.

que após a descriptografia nos diz o id do usuário, a data de expiração.

Essa é uma das principais vantagens do JWT: não é necessário fazer uma requisição extra para validar o token. Em outros fluxos do OAuth, temos que ir ao servidor de "identidade" para validar o token antes de autorizar.

E da para usar sem ter um pé atrás? porque o que estou pensando aqui é de, ao inves de guardar somente o id do usuário no payloader, guardar também uma chave, cujo rash vou armazenar no servidor, para ganhar mais uma camada de proteção. para mim assuta a ideia de não precisar dessa segunda camada... rsrs
> E da para usar sem ter um pé atrás? Sim, se você utilizar o JWT com "signed tokens", pois o sistema garante a integridade do seu JWT. > porque o que estou pensando aqui é de, ao inves de guardar somente o id do usuário no payloader, guardar também uma chave, cujo rash vou armazenar no servidor, para ganhar mais uma camada de proteção. O JWT, com "signed tokens", já faz algo similar, então não vejo necessidade alguma. Para clarificar o assunto, JWT é algo complexo. O básico parece fácil, mas eu recomendo que você leia a especificação e entenda como ele funciona com o seu fluxo de OAuth para compreender todos os detalhes. Além do mais, quero clarificar duas palavras-chave: **Integridade**: O JWT garante integridade, ou seja, se a sua aplicação recebe um token JWT, a aplicação pode verificar e ter a certeza de que o token e o conteúdo são íntegros. Ou seja, pertencem ao usuário no momento da autenticação, ao invés de alguém tentando se passar pelo usuário. **Criptografia**: O conteúdo do JWT não é criptografado, como outros já disseram, mas a transmissão deste JWT é encriptada com HTTPS. Ou seja, atores maliciosos não vão conseguir ver o conteúdo do JWT, mas o dono do JWT (no nosso exemplo, um usuário do seu aplicativo) vai conseguir ler o conteúdo do JWT. Em resumo, coloque informações que não são sensíveis, como identificadores, mas não coloque informações que o usuário não pode saber. O ID do usuário é um dado normalmente colocado em JWT.

Comentando sobre a necessidade de persistência, pode ser interessante implementar para que seja possível a funcionalidade de anular os JWTs já emitidos. Dessa maneira, seria necessário verificar na base de dados se o token ainda é válido antes de autenticar.

Obs.: caso queria inserir informações sensíveis no token, existe o conceito de JWE (superficialmente, jwt encriptado).

Acaba que ficou assim, indiretamente. eu não estou armazenando o token em sim, mas eu mapeio o dispositivo e gero um pass, que armazeno no token e, no servidor, armazeno o rash. o que faço a cada requisição é validar este rash. se o token invalidado (por exemplo, o usuario desconectando dispositivos, este rash já não será mais válido)

Basicamente é composto por: {Header}.{Payload}.{Assinatura}

Agora, se puder dar mais contexto sobre qual o motivo que chegou nesse assunto de implementar o JWT, quem sabe poderiamos te dar um norte melhor pra encontrar realmente uma saída eficiente.

A maioria implementa JWT onde não é necessário e em muitos casos autenticação por cookies é o suficiente com HttpOnly e SameSite pra ter uma segurança a mais.

Um dos pontos relevantes é a variedade de bibliotecas, que me permitirá ler o token na aplicação principal e em microserviços escritos em outras linguagens. para determinadas situações, ia precisar gerar uma autorização, persistir no banco de dados e o microserviço precisaria consultar o db antes de processar. Com o JWT, eu já consigo validar e dar seguimento ao processamento, sem etapas anteriores. Outro ponto também é o interesse de eliminar o uso de sessão, para escalar a aplicação com balanceador de carga, funções como serviço etc.
E como você tá fazendo essa autenticação hoje?
o token gerado guarda o user_id, o time em que foi gerado e um chave (gerada aleatoriamente e o rash dela é persistido no servidor). todas estas informações são validadas para confirmar a autenticação do usuário.