Crie Autenticação Segura com JWT
Aprenda a implementar autenticação segura com JWT (JSON Web Token) em aplicações Full Stack com React e Node.js!
Autenticação segura com JWT (JSON Web Token) funciona assim: no login, o backend valida as credenciais e devolve um token assinado; o frontend envia esse token no header Authorization a cada requisição, e um middleware verifica a assinatura antes de liberar as rotas protegidas — sem guardar sessão no servidor.
O que você vai ver aqui?
Introdução
Fala, impressionador!
Se você está desenvolvendo aplicações web, uma das coisas mais importantes que você precisa aprender é como criar um sistema de autenticação seguro. Não adianta nada ter uma aplicação incrível se qualquer pessoa consegue acessar rotas que deveriam ser privadas, certo?
Neste artigo, você vai aprender a implementar autenticação JWT (JSON Web Token) do zero, conectando front-end e back-end de forma segura. Vamos partir de um projeto básico de React com Node.js e adicionar toda a camada de segurança que um sistema profissional precisa.
O melhor de tudo? Vamos fazer isso passo a passo, de forma didática e prática. Ao final, você terá um sistema completo de login onde:
- O usuário faz login e recebe um token de autenticação
- Esse token é armazenado no navegador
- Todas as rotas protegidas verificam se o token é válido
- Se o usuário atualizar a página, ele continua logado
- Se tentar acessar uma rota sem estar autenticado, é redirecionado para o login
Isso é exatamente o que grandes aplicações como Netflix, Instagram e qualquer sistema profissional fazem. E você vai aprender a fazer também!
Para fazer o download do(s) arquivo(s) utilizados na aula, preencha com o seu e-mail:
Não vamos te encaminhar nenhum tipo de SPAM! A Hashtag Treinamentos é uma empresa preocupada com a proteção de seus dados e realiza o tratamento de acordo com a Lei Geral de Proteção de Dados (Lei n. 13.709/18). Qualquer dúvida, nos contate.
Preparado? Então vamos começar!
Preparando o ambiente
Para o exemplo deste artigo, você pode baixar o projeto do zero no material disponível da aula. Após baixar o projeto é necessário:
- Selecione a pasta "Do Zero", clique no ícone de três pontinhos e clique na opção Baixar;

- Descompactar a pasta. Para isso, clique com o botão direito do mouse sobre a pasta e selecione a opção Extrair tudo… em seguida clique no botão Extrair;

- Abrir a pasta no editor de código, por exemplo o VS Code;
- No interior da pasta baixada, teremos duas pastas principais: "back-end" e "front-end". Clique com o botão direito do mouse sobre cada uma delas e selecione a opção Open in integrated Terminal;

- Você precisará rodar o comando npm install no terminal de cada pasta para instalar as dependências do projeto;
- No terminal da pasta "back-end", use o comando npm start para rodar o back-end da aplicação;
- Em sequência, no terminal da pasta "front-end", use o comando npm run dev para inicializar o projeto;
- Acesse a aplicação com o link: "http://localhost:5173/login".
Pronto, o projeto inicial já está rodando e podemos seguir com a autenticação!
O que é JWT (JSON Web Token)?
JWT significa JSON Web Token, que é um padrão aberto (RFC 7519) para transmitir informações de forma segura entre cliente e servidor. Em outras palavras, o JWT é um token que contém dados codificados e uma assinatura que garante que esses dados não foram alterados.
Quando você faz login em um site, ao invés de o servidor precisar verificar sua senha toda hora, ele cria um token JWT que garante que o usuário(a) está autenticado e envia para você. Com isso, toda vez que você faz uma requisição, você manda esse token junto, e o servidor verifica se ele é válido.
Pense no JWT como se fosse uma pulseira de identificação em um festival: você mostra ela na entrada e consegue acessar o evento sem precisar comprar ingresso toda hora.
Estrutura de um token JWT
Um token JWT é dividido em três partes separadas por pontos:
- Header (cabeçalho): contém o tipo do token (JWT) e o algoritmo de criptografia usado;
- Payload (dados): contém as informações do usuário, como e-mail, ID e tempo de expiração;
- Signature (assinatura): garante que o token não foi modificado, usando uma chave secreta.
Então quando você recebe um token como: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFiY0BleGFtcGxlLmNvbSJ9.signature, essas três partes garantem a segurança da sua autenticação.
Por que usar JWT para autenticação?
Existem várias formas de fazer autenticação em aplicações web, mas o JWT tem se tornado cada vez mais popular por alguns motivos importantes:
- Stateless: o servidor não precisa guardar sessões, tudo está no token;
- Escalabilidade: funciona bem em sistemas distribuídos com múltiplos servidores;
- Segurança: a assinatura garante que o token não foi adulterado;
- Flexibilidade: você pode definir tempo de expiração e dados customizados;
- Padrão da indústria: amplamente usado e com bibliotecas para todas as linguagens.
Como funciona a autenticação com JWT?
O fluxo de autenticação com JWT funciona assim:
- Login: o usuário envia e-mail e senha para o servidor
- Verificação: o servidor verifica se os dados estão corretos
- Geração do token: se estiver certo, o servidor cria um JWT e envia para o cliente
- Armazenamento: o cliente guarda o token (geralmente no localStorage)
- Requisições: em toda requisição, o cliente envia o token no cabeçalho
- Validação: o servidor verifica se o token é válido antes de processar a requisição
- Acesso permitido: se o token for válido, o servidor processa a requisição normalmente
Esse processo garante que apenas usuários autenticados consigam acessar rotas protegidas da aplicação.
Criando o token de acesso
Dentro da pasta "back-end", no arquivo "server.js", na linha 19, há uma condição simples que verifica se o e-mail e a senha são iguais aos dados enviados pelo usuário(a) ao preencher o formulário. Caso sejam, o site é redirecionado para a página de saudação.
if (email === USUARIO && password === SENHA) {
res.redirect("http://localhost:5173/saudacao");
}É neste trecho que queremos criar a autenticação! Para isso precisamos instalar o JWT e isso pode ser feito da seguinte maneira:
- Clique com o botão direito do mouse sobre a pasta "back-end" e selecione a opção Open in Integrated Terminal;
- No novo terminal criado para o back-end, digite o comando: npm install jsonwebtoken e aguarde a instalação;
Em seguida, precisamos importar a biblioteca para dentro do arquivo "server.js". Por isso, ao final da linha três clique no botão Enter e, na linha 4 use o código: import jwt from "jsonwebtoken".
O próximo passo é criar o token de acesso toda vez que meu usuário(a) acessar o site. Para isso, dentro da condição if (email === USUARIO && password === SENHA) na linha 19, precisamos criar uma constante que vai receber como parâmetros:
- payload: dados de acesso do usuário(a), neste caso, "email" e "password";
- SecretKey: que podemos criar no arquivo ".env";
- informações extras: outros parâmetros opcionais como, tempo de expiração do token.
O código ficará assim:
if (email === USUARIO && password === SENHA) {
const accessToken = jwt.sign({ email, password }, ACCESS_TOKEN_KEY, {
expiresIn: "15m",
});
res.json({ accessToken });Lembre-se de adicionar no arquivo ".env" a ACCESS_TOKEN_KEY com um valor aleatório:
ACESS_TOKEN_KEY=[escreva um valor aleatório]Além disso, para que a chave de acesso seja processada é necessário adicioná-la à constante que contém as variáveis de ambiente na linha 10.
const { USUARIO, SENHA, ACCESS_TOKEN_KEY } = process.env;Enviando as informações pelo formulário
Na pasta "front-end" no arquivo "Login.jsx" dentro de "pages", atualmente estamos enviando diretamente as informações do formulário através do método POST sem autenticação. Contudo, vamos realizar algumas mudanças na maneira como as informações são enviadas para acessar a tela de saudação.
O primeiro passo é instalar a biblioteca Axios que usaremos para realizar a requisição do tipo POST. Caso queira explorar mais sobre essa biblioteca, recomendo o vídeo AXIOS vs FETCH: Qual a melhor forma de consumir APIs.
O processo de instalação é o seguinte:
- Clique com o botão direito do mouse sobre a pasta "front-end" e selecione a opção Open in Integrated Terminal;
- No novo terminal criado para o back-end, digite o comando: npm install axios e aguarde a instalação;
Em seguida, vamos importar as bibliotecas que usaremos:
import axios from "axios";
//Função React para manter e atualizar o estado local do componente
import { useState } from "react";
//Função para navegar entre rotas
import { useNavigate } from "react-router-dom";Na sequência, é necessário criar dois estados locais, um para email e outro para password, inicializados como strings vazias para armazenar os valores digitados nos inputs.
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");Também precisamos inicializar a função navigate, que permite redirecionar o usuário para outra rota, pois após receber a resposta bem-sucedida do servidor, o aplicativo deve redirecionar o usuário para a tela de saudação.
const navigate = useNavigate();O próximo passo é criar a função handleSubmit que vai fazer o envio do formulário e redirecionamento da rota:
const handleSubmit = async (e) => {
// Impede o comportamento padrão do formulário (recarregar a página)
e.preventDefault();
try {
// Envia uma requisição POST para o backend com email e senha
// O 'await' faz o código esperar a resposta antes de continuar
const { data } = await axios.post("http://localhost:3001/api/login", {
email, // valor digitado no input de email
password, // valor digitado no input de senha
});
// Armazena o token retornado pelo servidor no localStorage
// Isso permite manter o usuário logado entre páginas/reloads
localStorage.setItem("token", data.accessToken);
// Redireciona o usuário para a rota de saudacao após login bem-sucedido
navigate("/saudacao");
} catch (error) {
// Exibe um alerta caso o login falhe (email ou senha errados ou erro no servidor)
alert("Email ou senha inválidos!");
// Mostra detalhes técnicos do erro no console para ajudar no debug
console.error(`Deu algum erro: ${error}`);
}
};Agora com a função estruturada, precisamos inserí-la no formulário e capturar os valores adicionados em cada campo.
<form onSubmit={handleSubmit}>
<h1>Faça seu login</h1>
<input type="email" name="email" id="email" placeholder="Digite seu e-mail"
required onChange={(e) => setEmail(e.target.value)} />
<input type="password" name="password" id="password" placeholder="Digite sua senha"
required onChange={(e) => setPassword(e.target.value)} />
<button>Fazer login</button>
</form>O <form> chama a função handleSubmit ao submeter (onSubmit) e cada <input> tem:
- type apropriado (email / password) para validação nativa e teclado correto em mobile;
- required exige preenchimento (validação do navegador);
- onChange atualiza o estado email/password conforme o usuário digita.
O <button> envia o formulário (tipo padrão submit).
Verificando se o usuário(a) está autenticado na tela de saudação
Para validar se o usuário está realmente autenticado ao acessar a tela de saudação, precisamos confirmar se o token salvo no navegador ainda é válido. Como o token já foi gerado e armazenado no localStorage durante o login, o próximo passo é criar uma rota protegida no backend e fazer a verificação no frontend.
Dentro do arquivo server.js, na pasta back-end, criamos uma rota do tipo GET chamada /api/protected. Essa rota serve exclusivamente para verificar se o token enviado pelo cliente é válido. O código fica assim:
app.get("/api/protected", (req, res) => {
// Pega o header Authorization enviado pelo cliente
const authHeader = req.headers["authorization"];
// Extrai apenas o token (formato esperado: "Bearer <token>")
const token = authHeader ? authHeader.split(" ")[1] : undefined;
// Se não houver token, retorna erro 401 (não autorizado)
if (!token) res.status(401);
// Verifica se o token é válido usando a chave ACCESS_TOKEN_KEY
jwt.verify(token, ACCESS_TOKEN_KEY, (err, user) => {
// Se o token for inválido ou expirado, retorna erro 403 (proibido)
if (err) {
res.status(403);
return;
}
// Se estiver tudo certo, responde com mensagem e os dados do usuário contidos no token
res.json({ message: "Usuário autenticado", user });
});
});Essa rota realiza três verificações importantes:
- Confere se o token foi enviado no header Authorization;
- Valida o token usando a chave que foi usada para assiná-lo no login;
- Permite ou bloqueia o acesso, dependendo da validade do token.
Se o token estiver correto, a rota devolve os dados do usuário. Caso contrário, retorna erro 401 ou 403, indicando que o usuário deve fazer login novamente.
Agora, no arquivo "Saudacao.jsx", criamos um useEffect que roda automaticamente quando a página é carregada. Esse código verifica se o token ainda é válido antes de permitir que o usuário permaneça na tela:
useEffect(() => {
// Função que verifica se o usuário está autenticado
const checarAutenticacao = async () => {
// Pega o token salvo no navegador
const token = localStorage.getItem("token");
// Se não houver token, redireciona para o login
if (!token) navigate("/login");
try {
// Faz uma requisição GET para a rota protegida
// Envia o token no header Authorization
const response = await axios.get(
"http://localhost:3001/api/protected",
{
headers: { Authorization: `Bearer ${token}` },
}
);
// Se o backend retornar 401 ou 403, significa que o token é inválido
if (response.status === "401" || response.status === "403")
navigate("/login");
} catch (error) {
// Mostra o erro no console para ajudar a debugar
console.error(`Deu algum erro: ${error}`);
}
};
// Executa a verificação assim que o componente for montado
checarAutenticacao();
}, []);Esse trecho realiza uma série de verificações automáticas:
- Busca o token no localStorage;
- Caso não encontre, leva o usuário diretamente para o login;
- Envia o token para o backend para validar se ele ainda é válido;
- Caso o backend retorne erro (token inválido ou expirado), o usuário também é redirecionado;
- Isso impede que alguém acesse a tela da saudação simplesmente colando a URL no navegador.
Lembre-se de fazer as importações necessárias e criar a constante navigate para fazer a navegação para a página de login, caso o token esteja expirado.
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";const navigate = useNavigate();Implementando autenticação na tela Home
Caso tentemos acessar a página "http://localhost:5173/" não vamos conseguir e vamos cair em uma página em branco, pois no nosso projeto não temos essa rota definida.
O objetivo é criar essa página dentro da pasta "front-end/pages" para que ela redirecione a pessoa para a tela de login caso o(a) usuário(a) não esteja autenticado ou para a tela de saudação caso o(a) usuário(a) esteja autenticado. Para isso, podemos:
- Criar o arquivo "Home.jsx" dentro da pasta "front-end/pages";
- Utilizar o seguinte código:
import axios from "axios";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
const Home = () => {
const navigate = useNavigate(); // Hook para redirecionar o usuário
useEffect(() => {
// Função que valida se o usuário está autenticado
const checarAutenticacao = async () => {
const token = localStorage.getItem("token"); // Busca o token salvo
if (!token) navigate("/login"); // Se não houver token, vai para o login
try {
// Envia o token para o backend para validar
const response = await axios.get(
"http://localhost:3001/api/protected",
{
headers: { Authorization: `Bearer ${token}` }, // Token no header
}
);
// Se o token for inválido, redireciona para o login
if (response.status === "401" || response.status === "403") {
navigate("/login");
} else {
navigate("/saudacao"); // Se estiver tudo certo, vai para a saudação
}
} catch (error) {
console.error(`Deu algum erro: ${error}`); // Loga erros inesperados
}
};
checarAutenticacao(); // Executa a verificação ao montar o componente
}, []);
return <div>Home</div>; // Conteúdo simples da tela inicial
};
export default Home;Para que essa rota exista, precisamos abrir o arquivo "App.jsx" que está na pasta "front-end/src" e dentro da tag <Routes> criar a rota: <Route path="/" element={<Home />} />. Lembre-se de importar o arquivo "Home.jsx" no topo da página: import Home from "../pages/Home";
Pronto! Com isso, sempre que você acessar a página principal da aplicação através da URL "http://localhost:5173/", caso esteja autenticado e o token de acesso ainda esteja válido você será redirecionado para a tela de "Saudação', contudo, se o token estiver expirado ou você não tiver feito login, será redirecionado para a tela de "Login".
Perguntas frequentes
1. O que é JWT?
JSON Web Token é um padrão de token composto por três partes — header, payload e assinatura — codificadas em Base64. O payload carrega dados como id e permissões do usuário; a assinatura, gerada com uma chave secreta, garante que o conteúdo não foi adulterado.
2. Onde guardar o token JWT no frontend?
As duas opções têm trade-offs: cookie httpOnly protege contra roubo por XSS (o JavaScript não lê o token), enquanto localStorage é mais simples, porém exposto a scripts. Em produção, a combinação comum é cookie httpOnly + proteção CSRF e tokens de vida curta.
3. O que faz o middleware de autenticação?
Ele intercepta cada requisição às rotas protegidas: extrai o token do header, verifica assinatura e validade com a chave secreta e, se estiver tudo certo, anexa os dados do usuário à requisição e libera o fluxo. Token ausente ou inválido recebe resposta 401.
4. O JWT expira? Como renovar sem deslogar o usuário?
Sim — o claim exp define a validade, e tokens curtos (minutos a poucas horas) limitam o estrago de um vazamento. A renovação usa o refresh token: um token de vida longa, guardado com mais proteção, que emite novos access tokens sem pedir login de novo.
Conclusão
Neste artigo, aprendemos a criar tokens de acesso, verificá-los no servidor e proteger rotas tanto no back-end quanto no front-end. Com isso, você já possui os conhecimentos necessários para implementar sistemas de login seguros em seus próprios projetos.
Caso você queira aprender mais sobre desenvolvimento Full Stack, incluindo integração com bancos de dados, deploy e boas práticas de segurança, conheça nosso curso Fullstack Impressionador. Além disso, se preferir esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!
Além disso, caso prefira esse conteúdo no formato de vídeo-aula, pode acessar o vídeo no nosso canal do Youtube.
O que você aprende neste vídeo
Resposta rápida: A aula adiciona autenticação com JWT a um projeto React e Node já conectado, do login até as rotas protegidas. Você aprende a assinar o token com jwt.sign(), guardar a chave em variável de ambiente, expirar a sessão, salvar o token no localStorage, enviá-lo no header Authorization e validá-lo com jwt.verify() em cada acesso.
Neste vídeo (36 min):
- 1:30 - o problema: a tela de saudação abre sem login e a sessão se perde a cada F5
- 6:30 - criar o token no login com
jwt.sign(), passando o objeto do usuário como payload - 8:05 - guardar a chave secreta em variável de ambiente e definir a validade com
expiresIn - 9:05 - devolver o token com
res.json()e tratar o envio do formulário numhandleSubmit - 10:30 - trocar o POST nativo do formulário pelo Axios e guardar os campos com
useState - 14:00 - chamada com
async/awaitetry/catch, ee.preventDefault()para a página não recarregar - 16:55 - salvar o token no
localStoragee ir para a tela de saudação comuseNavigate - 19:35 - criar a rota
GET /api/protected, que responde se o usuário continua autenticado - 20:55 - mandar o token no header
Authorizationcom o prefixoBearerem cada requisição - 23:05 - ler o header no servidor e responder 401 sem token e 403 quando
jwt.verify()reprova - 27:05 - disparar a checagem uma vez só no
useEffect, com a lista de dependências vazia - 31:50 - repetir a proteção na tela Home e testar o fluxo apagando o token pelo navegador
Trechos do vídeo:
- O JWT dispensa guardar sessão no servidor: o token assinado viaja no header a cada requisição e o backend só confere a assinatura.
- A chave que assina o token fica em variável de ambiente no servidor, e é a mesma usada depois para verificar se o token é válido.
- O header chega no formato
Bearermais o token, separados por espaço: o servidor precisa dividir a string e usar a segunda parte. - Sem token o servidor responde 401, de não autorizado; com token inválido ou expirado, responde 403, de proibido.
Hashtag Treinamentos
Para acessar publicações de Full Stack, clique aqui!
Posts mais recentes de Full Stack
- LESS CSS: Guia Completo do Pré-processador (2026)LESS CSS é um pré-processador que adiciona variáveis, mixins, nesting e operações matemáticas ao CSS. Aprenda a configurar e usar com projeto prático.
- Variáveis no CSS (CSS Variables): Como Usar de Forma ProfissionalVocê sabe o que são Variáveis no CSS (CSS Variables)? Aprenda como usar técnicas que vão transformar a forma como você escreve variáveis CSS.
- Try Catch no JavaScript: Programação Defensiva na PráticaAprenda a usar try catch no JavaScript e melhore a sua programação defensiva!
Posts mais recentes da Hashtag Treinamentos
- Planilha de Controle de Notas Fiscais no Excel [Grátis]Baixe a planilha de controle de notas fiscais no Excel grátis: calcule ISS e retenções, veja o que está em aberto e gere a cobrança de cada nota de serviço.
- Qual IA usar na empresa: ChatGPT, Claude ou Perplexity?Qual IA usar na empresa: veja as diferenças entre ChatGPT, Claude e Perplexity e quando cada um rende mais em cada área da sua equipe.
- Apostilas Gratuitas em PDF: Excel, Power BI, Python e IABaixe apostilas gratuitas em PDF de Excel, Power BI, Python, Claude e agentes de IA, com exercícios e gabarito. Escolha a sua e comece hoje.









