This content originally appeared on DEV Community and was authored by Marcelo Magario
Eai devs!
Neste post, vou detalhar o passo a passo de como de como implementei a autenticação stateless usando Node.js
com TypeScript
, Express
, PostgreSQL
, e a dupla bcryptjs
para hashing de senhas e JSON Web Tokens (JWT
) para gerenciamento de sessão no meu projeto pessoal.
A Estrutura do Projeto
Para manter o código organizado, dividi a lógica em três partes principais:
1. authRoutes.ts: Define os endpoints /register
e /login
. Sua única responsabilidade é direcionar as requisições para o controller correto.
2. authController.ts: Contém a regra de negócio. É aqui que validamos os dados, interagimos com o banco e decidimos qual resposta enviar.
3. utils/auth.ts (Abstrato): Funções complementares para hashear senhas e gerar tokens, para não repetirmos código. Achei que ficou mais organizado desse jeito.
Passo 1: Registro do Usuário e Hashing da Senha
Nunca devemos salvar senhas em texto puro no banco de dados. A primeira etapa é garantir que a senha do usuário seja transformada em um hash irreversível. Para isso, usamos o bcryptjs
.
O controller authController.ts
cuida desse processo na função registerUser
:
import bcrypt from 'bcryptjs';
// Função conceitual que criei para hashear uma senha
async function criarHashSenha(senha: string): Promise<string> {
// O 'salt' adicionou uma camada extra de segurança ao hash
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(senha, salt);
return hash;
}
// Como eu usei:
// const hashDaSenha = await criarHashSenha(senhaDoUsuario);
// E então, salvei o `hashDaSenha` no meu banco de dados.
A função hashPassword
em utils/auth.ts
seria algo simples como:
// utils/auth.ts
import bcrypt from 'bcryptjs';
export const hashPassword = async (password: string): Promise<string> => {
const salt = await bcrypt.genSalt(10); // Gera um "sal" para fortalecer o hash
return await bcrypt.hash(password, salt);
};
Passo 2: gerando token de acesso do JWT
Após validar a senha no login com bcrypt.compare()
, o passo seguinte que implementei foi gerar o token. Um ponto de atenção que tive foi nunca deixar a chave secreta no código.
import jwt from 'jsonwebtoken';
// Função conceitual que usei para gerar um token
function gerarToken(idDoUsuario: string): string {
// 🔑 A chave secreta busquei das minhas variáveis de ambiente!
const chaveSecreta = process.env.JWT_SECRET;
if (!chaveSecreta) {
throw new Error('Chave secreta do JWT não definida!');
}
const payload = { id: idDoUsuario };
// Assinei o token com a chave e defini um tempo de expiração
return jwt.sign(payload, chaveSecreta, {
expiresIn: '1h' // Token expira em 1 hora
});
}
Passo 3: Middleware de proteção
Este foi o guardião que implementei para as minhas rotas. Neste exemplo, foquei apenas na lógica de verificação do token, que foi o coração do processo.
// Middleware conceitual que criei para proteger as rotas
function protegerRota(req: Request, res: Response, next: NextFunction) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
// Neguei o acesso se o token não foi fornecido
return res.status(401).json({ message: 'Acesso negado: token não fornecido.' });
}
try {
const token = authHeader.split(' ')[1];
const chaveSecreta = process.env.JWT_SECRET as string;
// jwt.verify() validou o token. Se fosse inválido, dispararia um erro.
const payloadVerificado = jwt.verify(token, chaveSecreta);
next(); // Token válido, liberei o acesso!
} catch (error) {
// Neguei o acesso se o token era inválido
return res.status(401).json({ message: 'Token inválido ou expirado.' });
}
}
O que acharam? vocês fariam diferente?
This content originally appeared on DEV Community and was authored by Marcelo Magario

Marcelo Magario | Sciencx (2025-06-07T21:19:26+00:00) Minha implementação de Autenticação com JWT e Bcrypt. Retrieved from https://www.scien.cx/2025/06/07/minha-implementacao-de-autenticacao-com-jwt-e-bcrypt/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.