Autenticação no Backend

Introdução à Autenticação

A autenticação é um componente crucial em qualquer aplicação backend, garantindo que apenas usuários autorizados possam acessar determinadas funcionalidades e recursos. Sem uma autenticação adequada, a segurança da aplicação fica comprometida, expondo dados sensíveis e funcionalidades críticas a acessos indevidos.

Neste módulo, vamos entender como implementar a autenticação no nosso sistema de loja simples, utilizando ferramentas modernas como bcrypt para criptografar senhas e JWT (JSON Web Token) para gerenciamento de tokens de autenticação.

Organização Básica do Código para Autenticação

Para manter o código organizado e de fácil manutenção, é importante seguir uma estrutura clara. A seguir, apresentamos uma organização básica das pastas e responsabilidades de cada camada no processo de autenticação:

Estrutura de Pastas Recomendada:

project-root/

├── controllers/
│   └── authController.js
├── services/
│   └── authService.js
├── repositories/
│   └── userRepository.js
├── utils/
│   └── hash.js
├── config/
│   └── jwtConfig.js
├── routes/
│   └── authRoutes.js
└── index.js

Descrição das Camadas:

  • Controller: Define as rotas e lida com as requisições relacionadas à autenticação.

  • Service: Contém a lógica de negócio para autenticação, como verificação de credenciais.

  • Repository: Acessa diretamente o banco de dados para buscar ou armazenar informações de usuários.

  • Utils: Funções utilitárias, como criptografia de senhas.

  • Config: Configurações gerais, como chaves secretas para tokens.

Passos para Implementar a Autenticação

Vamos seguir um passo a passo para implementar a autenticação no nosso projeto:

1. Preparar as Rotas de Usuário

Primeiro, precisamos configurar os endpoints para cadastro e login dos usuários.

// routes/authRoutes.js

const express = require('express');
const router = express.Router();
const authController = require('../controllers/authController');

// Rota para cadastro de usuário
router.post('/cadastro', authController.cadastro);

// Rota para login de usuário
router.post('/login', authController.login);

module.exports = router;

2. Criptografar Senhas com bcrypt

Para garantir a segurança das senhas dos usuários, utilizaremos a biblioteca bcrypt para criptografá-las antes de armazená-las no banco de dados.

Instalação do bcrypt:

npm install bcrypt

Implementação das Funções de Criptografia:

// utils/hash.js

const bcrypt = require('bcrypt');

// Função para gerar hash a partir da senha
exports.generate = (password) => {
    const salt = bcrypt.genSaltSync(10);
    return bcrypt.hashSync(password, salt);
};

// Função para comparar senha com hash
exports.compare = (password, hash) => {
    return bcrypt.compareSync(password, hash);
};

3. Implementação do Controller de Autenticação

O controller lida com as requisições de cadastro e login, utilizando os serviços apropriados.

// controllers/authController.js

const authService = require('../services/authService');

exports.cadastro = async (req, res) => {
    try {
        const usuario = await authService.cadastrarUsuario(req.body);
        res.status(201).json(usuario);
    } catch (error) {
        res.status(400).json({ mensagem: error.message });
    }
};

exports.login = async (req, res) => {
    try {
        const token = await authService.loginUsuario(req.body);
        res.status(200).json({ token });
    } catch (error) {
        res.status(400).json({ mensagem: error.message });
    }
};

4. Implementação do Service de Autenticação

O service contém a lógica de negócio para cadastro e login dos usuários.

// services/authService.js

const userRepository = require('../repositories/userRepository');
const hash = require('../utils/hash');
const tokenService = require('../services/tokenService');

exports.cadastrarUsuario = async (dados) => {
    const { nome, email, telefone, cpf, senha } = dados;

    // Verifica se o usuário já existe
    const existeUsuario = await userRepository.findByEmail(email);
    if (existeUsuario) {
        throw new Error('Este email já está cadastrado');
    }

    // Gera o hash da senha
    const senhaHash = hash.generate(senha);

    // Cria o novo usuário
    const novoUsuario = await userRepository.create({
        nome,
        email,
        telefone,
        cpf,
        senha: senhaHash,
    });

    return novoUsuario;
};

exports.loginUsuario = async (dados) => {
    const { email, senha } = dados;

    // Busca o usuário pelo email
    const usuario = await userRepository.findByEmail(email);
    if (!usuario) {
        throw new Error('Usuário/senha incorretos');
    }

    // Compara a senha fornecida com o hash armazenado
    const senhaValida = hash.compare(senha, usuario.senha);
    if (!senhaValida) {
        throw new Error('Usuário/senha incorretos');
    }

    // Gera o token JWT (a ser implementado na página "Tokens e Segurança")
    const tokenJWT = tokenService.generateToken({ id: usuario.id, email: usuario.email });
    return tokenJWT;
};

5. Implementação do Repository de Usuários

O repository acessa diretamente o banco de dados para buscar ou armazenar informações de usuários.

// repositories/userRepository.js

const prisma = require('../prismaClient');

exports.findByEmail = async (email) => {
    return await prisma.usuario.findUnique({
        where: { email },
    });
};

exports.create = async (dados) => {
    return await prisma.usuario.create({
        data: dados,
    });
};

6. Atualização das Rotas no Servidor

Integrar as rotas de autenticação no servidor principal.

// index.js

require('dotenv').config();
const express = require('express');
const app = express();
const port = 3000;

const produtosRouter = require('./routes/produtos');
const authRoutes = require('./routes/authRoutes');

app.use(express.json());

app.use('/produtos', produtosRouter);
app.use('/auth', authRoutes);

app.listen(port, () => {
    console.log(`Servidor rodando em http://localhost:${port}`);
});

Fluxo de Autenticação

  1. Cadastro de Usuário:

    • O usuário envia seus dados para o endpoint /auth/cadastro.

    • A senha é criptografada utilizando bcrypt.

    • Os dados do usuário são armazenados no banco de dados sem gerar um token.

  2. Login:

    • O usuário envia suas credenciais para o endpoint /auth/login.

    • As credenciais são verificadas e, se válidas, um token JWT é gerado e retornado (a implementação completa do token será detalhada na página "Tokens e Segurança").

Last updated

Was this helpful?