Por que segurança em APIs é crítica?

APIs são a espinha dorsal de aplicações modernas. Uma vulnerabilidade pode resultar em:

  • Vazamento de dados sensíveis
  • Acesso não autorizado
  • Denial of Service (DoS)
  • Perda de confiança dos usuários
  • Consequências legais e financeiras

1. Autenticação e Autorização

JWT (JSON Web Tokens)

JWT é o padrão moderno para autenticação stateless:

// Gerar token
const jwt = require('jsonwebtoken');
const token = jwt.sign(
    { userId: user.id, email: user.email },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
);

// Verificar token
const verifyToken = (req, res, next) => {
    const token = req.headers.authorization?.split(' ')[1];
    
    if (!token) {
        return res.status(401).json({ error: 'Token não fornecido' });
    }
    
    try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        req.user = decoded;
        next();
    } catch (error) {
        return res.status(401).json({ error: 'Token inválido' });
    }
};

OAuth 2.0

Para aplicações mais complexas, use OAuth 2.0 com fluxos apropriados (Authorization Code, Client Credentials, etc.).

API Keys

Para acesso de aplicações, use API keys com rotação periódica:

// Middleware de validação de API Key
const validateApiKey = (req, res, next) => {
    const apiKey = req.headers['x-api-key'];
    
    if (!apiKey || !isValidApiKey(apiKey)) {
        return res.status(401).json({ error: 'API Key inválida' });
    }
    
    req.apiKey = apiKey;
    next();
};

2. HTTPS - Sempre Use

HTTPS é obrigatório. Nunca exponha APIs em HTTP:

  • Criptografa dados em trânsito
  • Previne man-in-the-middle attacks
  • Protege credenciais
  • Melhora SEO e confiança

3. Rate Limiting

Proteja sua API contra abuso e DoS:

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutos
    max: 100, // máximo 100 requests
    message: 'Muitas requisições, tente novamente mais tarde',
    standardHeaders: true,
    legacyHeaders: false,
});

app.use('/api/', limiter);

// Rate limiting por IP e por usuário
const userLimiter = rateLimit({
    windowMs: 60 * 60 * 1000, // 1 hora
    max: 10, // 10 requisições por hora por usuário
    keyGenerator: (req) => req.user?.id || req.ip,
});

4. Validação de Dados

Valide e sanitize todos os dados de entrada:

const { body, validationResult } = require('express-validator');

const validateUser = [
    body('email').isEmail().normalizeEmail(),
    body('password').isLength({ min: 8 }).matches(/[A-Z]/).matches(/[0-9]/),
    body('name').trim().escape().isLength({ min: 2, max: 50 }),
    (req, res, next) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({ errors: errors.array() });
        }
        next();
    }
];

5. Proteção contra SQL Injection

Use prepared statements ou ORMs:

// ❌ NUNCA faça isso
const query = `SELECT * FROM users WHERE email = '${email}'`;

// ✅ Use prepared statements
const query = 'SELECT * FROM users WHERE email = ?';
db.query(query, [email], (err, results) => {
    // ...
});

// ✅ Ou use ORM
const user = await User.findOne({ where: { email } });

6. CORS (Cross-Origin Resource Sharing)

Configure CORS adequadamente:

const cors = require('cors');

const corsOptions = {
    origin: process.env.ALLOWED_ORIGINS.split(','),
    credentials: true,
    optionsSuccessStatus: 200,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key'],
};

app.use(cors(corsOptions));

7. Headers de Segurança

Configure headers de segurança HTTP:

const helmet = require('helmet');

app.use(helmet({
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'"],
        },
    },
    hsts: {
        maxAge: 31536000,
        includeSubDomains: true,
        preload: true
    }
}));

8. Logging e Monitoramento

Registre atividades suspeitas:

const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' }),
    ],
});

// Log de requisições suspeitas
app.use((req, res, next) => {
    if (req.statusCode >= 400) {
        logger.warn({
            ip: req.ip,
            method: req.method,
            url: req.url,
            statusCode: res.statusCode,
        });
    }
    next();
});

9. Sanitização de Erros

Nunca exponha detalhes internos em erros:

// ❌ Ruim
res.status(500).json({ error: err.message });

// ✅ Bom
if (process.env.NODE_ENV === 'production') {
    res.status(500).json({ error: 'Erro interno do servidor' });
} else {
    res.status(500).json({ error: err.message });
}

10. Versionamento de API

Versione sua API para permitir mudanças sem quebrar clientes:

app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);

Checklist de Segurança

  • ✅ HTTPS em produção
  • ✅ Autenticação implementada
  • ✅ Autorização por roles/permissões
  • ✅ Rate limiting configurado
  • ✅ Validação de entrada
  • ✅ Proteção contra SQL injection
  • ✅ CORS configurado corretamente
  • ✅ Headers de segurança
  • ✅ Logging de segurança
  • ✅ Secrets em variáveis de ambiente
  • ✅ Sanitização de erros
  • ✅ Testes de segurança

Ferramentas de Teste

  • OWASP ZAP: Scanner de vulnerabilidades
  • Postman: Testes de API
  • Burp Suite: Análise de segurança
  • npm audit: Verificar dependências

Lembre-se: Segurança não é um produto, é um processo. Revise e atualize constantemente suas práticas de segurança.