Ir para conteúdo

Autenticação Segura com JWT

Techpoint.
12 Mar 2026
main image

Imagina uma aplicação web ou móvel onde o utilizador faz login com o seu email e a palavra-passe. Após esta ação, o utilizador consegue consultar os seus dados, realizar diversas operações e até navegar entre várias páginas.

Como é que o servidor sabe se um determinado utilizador continua autenticado, mesmo depois de ter fechado a aplicação e reaberto mais tarde?

É aqui que entram os "JSON Web Tokens" (ou "JWT"). Trata-se de um método de autenticação baseado em "tokens" que permite, de forma segura, comunicar entre sistemas.

1. Autenticação inicial do utilizador

O primeiro passo no processo de autenticação é criar um registo. Após escolher o email e a palavra-passe, é enviado um pedido ao servidor.

Caso o registo seja aceite, por razões de segurança, a palavra-passe nunca é armazenada diretamente na base de dados.

1.1 Hash

Em vez de armazenar a palavra-passe diretamente na base de dados, no servidor aplicámos um processo chamado "hashing". Este processo transforma a palavra-passe num conjunto de letras e números aparentemente aleatório.

O resultado disso é uma "hash" que fica armazenada na base de dados, associada ao utilizador em questão.

Quando o utilizador pretende fazer login, acede com o seu email e a palavra-passe original.

Mas como isso é possível, se na base de dados não temos a palavra-passe guardada?

O servidor aplica a mesma função usada para codificar a palavra-passe, ao criar o seu registo, para gerar uma "hash" da palavra-passe inserida no processo de login.

Se as duas "hashes" forem iguais, significa que o utilizador introduziu as credenciais corretas e, neste caso, pode ser autenticado.

Através de uma "hash" nunca conseguimos saber qual a palavra-passe original que foi escolhida. Para criar, usámos bibliotecas como bcrypt ou argon2.

Este método tem uma grande vantagem ao nível da segurança, caso alguém consiga aceder à base de dados, nunca terá acesso às palavras-passe dos utilizadores.

1.2. Salt

Outra consideração importante para a segurança. Como garantimos que uma determinada palavra-passe nunca gera a mesma "hash"?

Isto é muito importante para impedir certos ataques ao sistema, usando uma tabela de "hashes" pré-calculadas para palavras-passe comuns. Para evitar isto, usamos o "Salt".

Trata-se de um código aleatório adicionado à palavra-passe original, antes de esta ser codificada, para gerar sempre "hashes" distintos.

Este código também é armazenado na base de dados, juntamente com a "hash", para depois ser comparado quando o utilizador faz login.

content image
2. Estrutura do "JWT"

Após o processo de autenticação, é gerado um "token JWT" que é associado ao utilizador na aplicação, este token deverá sempre estar presente em todos os pedidos ao servidor.

Desta forma, garantimos que o utilizador permanece autenticado.

Um "token" é um código composto por 3 partes: HEADER.PAYLOAD.SIGNATURE

No Header temos a informação sobre o algoritmo e o tipo de token, com os seguintes campos:

  • alg: tipo de algoritmo utilizado, por exemplo HS256 ou RS256;

  • typ: tipo de token, neste caso "JWT"

Para o Payload, precisamos de incluir informações sobre o token e o próprio utilizador.

Atenção, esta informação nunca é encriptada, por isso não devemos usar dados sensíveis (como palavra-passe).

  • sub: aqui indicámos algum campo que permita identificar o utilizador na base de dados, por exemplo um "ID" interno (um código identificador único)

  • iat: data de criação do token

  • exp: data de expiração do token

Por fim, a Signature. Este código depende do "Header" e do "Payload" e garante que o "token" não foi alterado desde que foi gerado pelo servidor.

Para isso, usámos uma chave secreta configurada no servidor para garantir a integridade e a validade do "token".

Caso o "token" seja alterado de forma maliciosa, a "Signature" vai verificar que o "token" já não é válido e o servidor rejeitará o pedido.

O "token" não tem um conceito de estado (por exemplo, ativo/inativo). É válido desde a data de emissão até à sua data de expiração.

Quando expira, o utilizador deve fazer um novo pedido de autenticação.

3. Usar o "JWT token"

Após o "token" ser gerado e devolvido pelo servidor, temos de o armazenar na nossa aplicação de forma a estar disponível em todos os futuros pedidos ao servidor.

 

3.1. Como guardar

Existem diferentes formas de armazenar:

LocalStorage: permite manter o "token" guardado, mesmo após fechar a aplicação. No entanto, é vulnerável a ataques maliciosos (por exemplo, ataques XSS);

SessionStorage: fica associado apenas à "tab" do navegador que está aberta. Ao fechar essa "tab", o "token" será apagado. Um pouco mais seguro, mas ainda vulnerável a XSS;

Cookies: podemos definir uma data de expiração, tornando-se mais seguro. Podemos definir diversas opções tais como:

  • Secure: só permite enviar dados através de uma ligação com HTTPS;

  • HttpOnly: não permite que "javascript" consiga ler o token; desta forma, bloqueamos os ataques XSS;

  • SameSite: reduz o risco de ataques CSRF;

Em apps móveis, podemos usar o armazenamento seguro do sistema, como o "Keychain" (iOS) ou o "EncryptedSharedPreferences" (Android).

A regra fundamental é guardar o "token" de forma a que "scripts" maliciosos não consigam aceder ao mesmo.

3.2. Como usar

De forma a que o servidor saiba que o utilizador continua autenticado, o "token" deve ser incluído em cada pedido.

A forma padrão é através de um "header HTTP", chamado "Authorization":

GET /api/my-info

Authorization: Bearer <TOKEN>

"Bearer" indica que o "header" contém um "token" de acesso.

O servidor, ao receber este pedido, vai efetuar os seguintes passos:

  • Lê o "token" e verifica a assinatura e os dados do mesmo (por exemplo, data de expiração);

  • Se for válido, o é pedido autorizado;

  • Se for inválido ou expirado, o pedido é rejeitado (por norma, é devolvido um erro "401 Unauthorized");

content image
4. Boas práticas e segurança

Sendo o "token" algo que mantém o utilizador autenticado e permite realizar operações com os seus dados, temos de garantir sempre a segurança.

4.1. Expiração do "token"

Um "token" não deve ser válido por muito tempo. Caso haja um ataque e seja interceptado, podem usar o "token" para agir em nome do utilizador e, provavelmente, roubar os seus dados.

Uma boa prática é gerar "tokens" curtos, ou seja, que expiram em poucos minutos após serem criados. Desta forma, mesmo que alguém tenha acesso ao "token", só será útil por um breve período.

No entanto, isto acarreta uma complicação para o utilizador. Se, por exemplo, definir um tempo máximo de 15 minutos, o utilizador tem de efetuar login a cada 15 minutos, o que poderá causar fadiga e perda de interesse na aplicação.

Mas existe uma solução, o "Refresh Token".

Um "Refresh Token" é apenas um "token" com um tempo de vida mais longo, usado para gerar e obter novos "JWT tokens" quando estes expiram, de forma a permitir que o utilizador continue autenticado.

A estratégia usada normalmente:

  • JWT Token: curto prazo de vida, usado nos pedidos ao servidor

  • Refresh Token: maior prazo de vida, gerado quando o utilizador faz login, e guardado da mesma forma que o "JWT Token"

Na aplicação teríamos o seguinte fluxo:

  • O "JWT Token" expira. Em vez do utilizador ter de fazer login novamente, a aplicação pausa momentaneamente (sem o utilizador dar conta);

  • A aplicação envia o "Refresh Token" para o servidor de forma a gerar um novo "JWT Token";

  • Se o "Refresh Token" for válido, o servidor emite um novo "JWT Token" e o utilizador continua autenticado. Caso contrário, terá de fazer login novamente.

Isto é muito útil com esta configuração, por exemplo:

  • JWT Token: expira em 15 minutos

  • Refresh Token: expira em 90 dias

Isto significa que, caso o "token" seja interceptado, é válido apenas por breves instantes. Mas o utilizador consegue ficar autenticado durante 90 dias, pois o sistema continua a gerar novos "tokens" de acesso sempre que necessário.

4.3. Invalidar "JWT Tokens"

Como referido, o "token" não tem um conceito de estado (ativo/inativo) e não existe nenhuma função para cancelá-lo, caso o mesmo seja interceptado, por exemplo.

Ele é válido desde que é gerado até à sua data de expiração. Mesmo que o utilizador faça "logout" na aplicação, o "token" continua válido.

No entanto, existem outras formas de garantir a segurança.

4.3.1. Versões de "tokens"

A forma mais simples de invalidar um "token" é implementar um campo "tokenVersion" na base de dados e incrementá-lo a cada vez que o utilizador fizer "logout" na aplicação. Ao gerar um novo "token", incluímos este campo no payload. Quando o utilizador fizer "logout", o valor vai incrementar e o "token" vai deixar de ser válido.

4.3.2 Blacklist

Este sistema funciona por utilizador, ou seja, todos os "tokens" antigos ficam inválidos quando incrementamos este campo. É um método simples, rápido e não precisamos de guardar listas enormes com todos os "tokens" gerados.

Cada vez que um utilizador faz "logout", guardar no servidor uma lista com o "token".

Desta forma, se um "token" desta lista for usado, conseguimos bloquear o acesso.

Mais limitado, precisa de armazenamento e também uma função para limpar regularmente esta lista de forma a não crescer indefinidamente.

4.3.3. Armazenamento em "Redis"

"Redis" é um armazenamento em memória rápido, que permite consultar os "tokens" guardados muito rapidamente.

Permite também definir um TTL (Time to Live) automático, eliminando, desta forma, os "tokens" expirados sem intervenção manual.

Assim, quando o utilizador faz login, guardamos o novo "token" no "Redis" e sabemos que enquanto o "token" estiver neste armazenamento, continua a ser válido.

5. Conclusão

A autenticação com "JWT Token" permite que as aplicações mantenham os utilizadores autenticados de forma simples e segura. Seguindo estes passos, conseguimos criar um sistema robusto, onde o utilizador pode manter os seus dados protegidos.

Segurança não é um detalhe; é prioridade.

author image
Rui SáFullstack Developer
Partilha
Mais artigos interessantes
related post image
Techpoint.
Gestão de Projetos com Agile
related post image
Techpoint.
O que o cliente quer VS o que precisa
related post image
Techpoint.
Limpar a cache do navegador: Como e Porquê?
Partilha
Utilizamos os nossos próprios cookies para lhe proporcionar uma melhor experiência. Para saber que cookies utilizamos e como os desativar, leia a política de cookies. Ao ignorar ou fechar esta mensagem, e a menos que tenha desativado os cookies, está a concordar com a sua utilização neste dispositivo.
Aceitar
Saber mais