As APIs REST representam o padrão fundamental para comunicação entre aplicações modernas. Node.js destaca-se como plataforma preferida para desenvolver APIs escaláveis devido à sua arquitetura orientada a eventos e performance superior. Este tutorial demonstra a criação de uma API REST completa com autenticação JWT (JSON Web Tokens).

JSON Web Tokens revolucionaram a autenticação em aplicações distribuídas. São tokens autocontidos que carregam informações do usuário codificadas e assinadas digitalmente, eliminando consultas constantes ao banco de dados e melhorando significativamente a performance das aplicações.

Configurando o Ambiente de Desenvolvimento

Inicie criando um novo projeto Node.js com as dependências necessárias:

mkdir api-jwt-tutorial && cd api-jwt-tutorial
npm init -y
npm install express jsonwebtoken bcryptjs cors helmet dotenv
npm install --save-dev nodemon

As bibliotecas incluem Express para roteamento, jsonwebtoken para manipulação de JWTs, bcryptjs para hash de senhas, cors para controle de acesso, helmet para segurança adicional e dotenv para variáveis de ambiente.

Estrutura do Servidor Base

Crie o arquivo server.js com a configuração inicial:

const express = require(\'express\');
const jwt = require(\'jsonwebtoken\');
const bcrypt = require(\'bcryptjs\');
const cors = require(\'cors\');
const helmet = require(\'helmet\');
require(\'dotenv\').config();

const app = express();
const PORT = process.env.PORT || 3000;
const JWT_SECRET = process.env.JWT_SECRET || \'sua-chave-secreta-muito-forte\';

// Middlewares de segurança
app.use(helmet());
app.use(cors());
app.use(express.json({ limit: \'10mb\' }));
app.use(express.urlencoded({ extended: true }));

// Simulação de banco de dados
let users = [];
let posts = [];

app.listen(PORT, () => {
  console.log(
Servidor rodando na porta ${PORT}
); });

Implementando Autenticação de Usuários

O sistema de autenticação requer endpoints para registro, login e validação de tokens. Implemente os controladores de usuário:

// Endpoint de registro
app.post(\'/api/register\', async (req, res) => {
  try {
    const { username, email, password } = req.body;
    
    // Validações básicas
    if (!username || !email || !password) {
      return res.status(400).json({ 
        error: \'Todos os campos são obrigatórios\' 
      });
    }
    
    if (password.length < 6) {
      return res.status(400).json({ 
        error: \'Senha deve ter pelo menos 6 caracteres\' 
      });
    }
    
    // Verificar se usuário já existe
    const existingUser = users.find(u => u.email === email);
    if (existingUser) {
      return res.status(409).json({ 
        error: \'Usuário já cadastrado\' 
      });
    }
    
    // Criptografar senha
    const saltRounds = 12;
    const hashedPassword = await bcrypt.hash(password, saltRounds);
    
    // Salvar usuário
    const newUser = {
      id: users.length + 1,
      username,
      email,
      password: hashedPassword,
      createdAt: new Date().toISOString()
    };
    
    users.push(newUser);
    
    // Remover senha da resposta
    const { password: _, ...userResponse } = newUser;
    
    res.status(201).json({
      message: \'Usuário criado com sucesso\',
      user: userResponse
    });
    
  } catch (error) {
    res.status(500).json({ error: \'Erro interno do servidor\' });
  }
});

// Endpoint de login
app.post(\'/api/login\', async (req, res) => {
  try {
    const { email, password } = req.body;
    
    if (!email || !password) {
      return res.status(400).json({ 
        error: \'Email e senha são obrigatórios\' 
      });
    }
    
    // Buscar usuário
    const user = users.find(u => u.email === email);
    if (!user) {
      return res.status(401).json({ 
        error: \'Credenciais inválidas\' 
      });
    }
    
    // Verificar senha
    const isValidPassword = await bcrypt.compare(password, user.password);
    if (!isValidPassword) {
      return res.status(401).json({ 
        error: \'Credenciais inválidas\' 
      });
    }
    
    // Gerar JWT
    const token = jwt.sign(
      { 
        userId: user.id, 
        username: user.username, 
        email: user.email 
      },
      JWT_SECRET,
      { 
        expiresIn: \'24h\',
        issuer: \'api-jwt-tutorial\'
      }
    );
    
    res.json({
      message: \'Login realizado com sucesso\',
      token,
      user: {
        id: user.id,
        username: user.username,
        email: user.email
      }
    });
    
  } catch (error) {
    res.status(500).json({ error: \'Erro interno do servidor\' });
  }
});

Criando Middleware de Autenticação JWT

O middleware de autenticação intercepta requisições protegidas e valida tokens JWT:

const authenticateJWT = (req, res, next) => {
  const authHeader = req.header(\'Authorization\');
  
  if (!authHeader || !authHeader.startsWith(\'Bearer \')) {
    return res.status(401).json({ 
      error: \'Token de acesso requerido\' 
    });
  }
  
  const token = authHeader.substring(7); // Remove \'Bearer \'
  
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    if (error.name === \'TokenExpiredError\') {
      return res.status(401).json({ 
        error: \'Token expirado\' 
      });
    }
    
    if (error.name === \'JsonWebTokenError\') {
      return res.status(401).json({ 
        error: \'Token inválido\' 
      });
    }
    
    return res.status(500).json({ 
      error: \'Erro na validação do token\' 
    });
  }
};

Implementando Rotas Protegidas

Demonstre o uso do middleware criando endpoints para gerenciar posts:

// Listar posts (rota protegida)
app.get(\'/api/posts\', authenticateJWT, (req, res) => {
  const userPosts = posts.filter(post => post.userId === req.user.userId);
  
  res.json({
    posts: userPosts,
    total: userPosts.length
  });
});

// Criar novo post (rota protegida)
app.post(\'/api/posts\', authenticateJWT, (req, res) => {
  const { title, content } = req.body;
  
  if (!title || !content) {
    return res.status(400).json({ 
      error: \'Título e conteúdo são obrigatórios\' 
    });
  }
  
  const newPost = {
    id: posts.length + 1,
    title,
    content,
    userId: req.user.userId,
    author: req.user.username,
    createdAt: new Date().toISOString()
  };
  
  posts.push(newPost);
  
  res.status(201).json({
    message: \'Post criado com sucesso\',
    post: newPost
  });
});

// Perfil do usuário (rota protegida)
app.get(\'/api/profile\', authenticateJWT, (req, res) => {
  const user = users.find(u => u.id === req.user.userId);
  
  if (!user) {
    return res.status(404).json({ 
      error: \'Usuário não encontrado\' 
    });
  }
  
  const { password: _, ...userProfile } = user;
  
  res.json({
    profile: userProfile,
    postsCount: posts.filter(p => p.userId === user.id).length
  });
});

Melhorias de Segurança e Performance

Implemente recursos avançados para produção, incluindo rate limiting e refresh tokens. Para projetos que exigem alta disponibilidade, considere utilizar servidores VPS especializados que oferecem recursos dedicados para APIs Node.js.

Configure variáveis de ambiente no arquivo .env:

JWT_SECRET=sua-chave-jwt-super-secreta-de-pelo-menos-256-bits
PORT=3000
NODE_ENV=development
BCRYPT_ROUNDS=12

Para aplicações em produção, integre bancos de dados como PostgreSQL ou MongoDB e implemente cache com Redis. Considere também otimizações de SEO se sua API servir conteúdo para aplicações web.

Testando a API

Teste os endpoints usando curl ou ferramentas como Postman:

Registrar usuário

curl -X POST http://localhost:3000/api/register \\ -H "Content-Type: application/json" \\ -d \'{"username":"teste","email":"teste@email.com","password":"123456"}\'

Fazer login

curl -X POST http://localhost:3000/api/login \\ -H "Content-Type: application/json" \\ -d \'{"email":"teste@email.com","password":"123456"}\'

Acessar rota protegida

curl -X GET http://localhost:3000/api/profile \\ -H "Authorization: Bearer SEU_TOKEN_JWT_AQUI"