Acesse o painel da sua conta

Não tem uma conta? Registrar

Entrar em contato

Visite também nosso site craftxp.com.br

  • img
  • img
  • img
  • img
  • img
  • img

Entre em contato

OAuth 2.0 e JWT: Autenticação e Autorização Moderna para APIs REST

OAuth 2.0 e JWT: Autenticação e Autorização Moderna para APIs REST

Proteger uma API REST não é apenas uma questão de autenticação (quem é você?), mas também de autorização (o que você pode fazer?). Neste artigo, vamos mergulhar nos dois pilares da segurança moderna de APIs: o protocolo OAuth 2.0 e o formato JWT (JSON Web Token).

O que é OAuth 2.0?

OAuth 2.0 é um protocolo de autorização que permite que aplicações obtenham acesso limitado a recursos em nome de um usuário. Diferente de um login tradicional onde você entrega sua senha para cada serviço, o OAuth 2.0 usa tokens de acesso com escopos bem definidos.

Criado pelo IETF (RFC 6749), o OAuth 2.0 é o padrão utilizado por gigantes como Google, GitHub, Facebook e Microsoft para autorizar aplicações de terceiros.

💡 "OAuth 2.0 não é um protocolo de autenticação — é um protocolo de autorização. Mas ele é frequentemente combinado com JWT para construir sistemas completos de autenticação."

Os 4 Papéis do OAuth 2.0

  1. Resource Owner (Proprietário do Recurso): O usuário que possui os dados. Ex: você no Google.
  2. Client (Cliente): A aplicação que quer acessar os dados. Ex: um app de terceiros.
  3. Authorization Server (Servidor de Autorização): Emite os tokens após autenticar o usuário. Ex: servidor do Google.
  4. Resource Server (Servidor de Recursos): Hospeda os dados protegidos e valida o token. Ex: API do Google Drive.

O que é JWT?

JWT (JSON Web Token) é um formato compacto e seguro para transmitir informações entre duas partes como um objeto JSON. Ele é autocontido — todas as informações necessárias estão dentro do próprio token.

Um JWT é composto por três partes separadas por pontos (.) e codificadas em Base64URL:

HEADER.PAYLOAD.SIGNATURE

# Exemplo:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkxlbyIsImlhdCI6MTUxNjIzOTAyMn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_aQssw5c

Estrutura do JWT

1. Header

Contém o tipo do token e o algoritmo de assinatura:

{
  "alg": "HS256",
  "typ": "JWT"
}

2. Payload (Claims)

Contém as claims — afirmações sobre o usuário e metadados do token. Existem claims registradas (padrão) e personalizadas:

{
  "sub": "user_123",          // Subject — ID do usuário
  "name": "Leonardo Mendes",  // Claim personalizada
  "iat": 1747353600,          // Issued At — emitido em
  "exp": 1747360800,          // Expiration — expira em
  "iss": "https://api.exemplo.com", // Issuer — emissor
  "aud": "app-frontend"      // Audience — público-alvo
}

3. Signature

Garante que o token não foi adulterado. É gerada combinando header + payload + uma chave secreta:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

Fluxos de Autorização do OAuth 2.0

1. Authorization Code Flow (Recomendado)

É o fluxo mais seguro para aplicações web e mobile. O cliente nunca vê o token diretamente — ele recebe um código de autorização que é trocado por um token no backend.

Usuário  →  Frontend  →  Authorization Server  →  Código
                ↓
          Backend (troca código por token)
                ↓
          Token armazenado no servidor

Passo a passo:

  1. Usuário clica em "Login com Google"
  2. O frontend redireciona para o Google (Authorization Server) com os parâmetros: client_id, redirect_uri, response_type=code, scope
  3. Usuário faz login e autoriza a aplicação
  4. Google redireciona de volta com um code na URL
  5. O backend troca o code por um access_token (e opcionalmente um refresh_token)

2. Client Credentials Flow

Usado para comunicação máquina-a-máquina (server-to-server). Não envolve usuário final:

POST /oauth/token HTTP/1.1
Content-Type: application/json

{
  "grant_type": "client_credentials",
  "client_id": "seu-client-id",
  "client_secret": "seu-client-secret"
}

Resposta:
{
  "access_token": "eyJhbGci...",
  "token_type": "Bearer",
  "expires_in": 3600
}

3. Implicit Flow (DEPRECATED)

Antigamente usado em SPAs, hoje é fortemente desencorajado por questões de segurança. Prefira o Authorization Code Flow com PKCE.

Implementação Prática: Autenticação com JWT em Node.js

Backend: Gerando Tokens

const jwt = require('jsonwebtoken');

function gerarToken(usuario) {
  const payload = {
    sub: usuario.id,
    nome: usuario.nome,
    email: usuario.email,
    perfil: usuario.perfil
  };

  return jwt.sign(payload, process.env.JWT_SECRET, {
    expiresIn: '1h',
    issuer: 'https://api.exemplo.com'
  });
}

// Uso no login:
app.post('/login', async (req, res) => {
  const { email, senha } = req.body;
  const usuario = await autenticarUsuario(email, senha);

  if (!usuario) {
    return res.status(401).json({ erro: 'Credenciais inválidas' });
  }

  const token = gerarToken(usuario);
  res.json({ access_token: token, token_type: 'Bearer' });
});

Middleware de Autenticação

function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;

  if (!authHeader) {
    return res.status(401).json({ erro: 'Token não fornecido' });
  }

  // Formato esperado: "Bearer eyJhbGci..."
  const parts = authHeader.split(' ');
  if (parts.length !== 2 || parts[0] !== 'Bearer') {
    return res.status(401).json({ erro: 'Formato inválido' });
  }

  const token = parts[1];

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.usuario = decoded;
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ erro: 'Token expirado' });
    }
    return res.status(401).json({ erro: 'Token inválido' });
  }
}

// Protegendo rotas:
app.get('/api/perfil', authMiddleware, (req, res) => {
  res.json({ usuario: req.usuario });
});

Refresh Token na Prática

Access tokens têm curta duração (15 min a 1 hora). Para evitar que o usuário faça login repetidamente, usamos refresh tokens:

function gerarRefreshToken(usuario) {
  const payload = { sub: usuario.id, type: 'refresh' };
  return jwt.sign(payload, process.env.JWT_REFRESH_SECRET, {
    expiresIn: '7d'
  });
}

app.post('/refresh', async (req, res) => {
  const { refresh_token } = req.body;

  try {
    const decoded = jwt.verify(refresh_token, process.env.JWT_REFRESH_SECRET);

    if (decoded.type !== 'refresh') {
      return res.status(400).json({ erro: 'Token inválido' });
    }

    const usuario = await buscarUsuario(decoded.sub);
    const novoAccessToken = gerarToken(usuario);

    res.json({ access_token: novoAccessToken });
  } catch (err) {
    return res.status(401).json({ erro: 'Refresh token inválido ou expirado' });
  }
});

Boas Práticas de Segurança

  • Use HTTPS sempre: Tokens JWT trafegam no header da requisição. Sem HTTPS, eles podem ser interceptados.
  • Armazene tokens com segurança: No frontend web, prefira httpOnly cookies em vez de localStorage (vulnerável a XSS).
  • Defina expiração curta: Access tokens de 15-60 minutos. Refresh tokens de 7-30 dias.
  • Use escopos (scopes): Limite o que o token pode fazer. Ex: read:posts, write:posts.
  • Não coloque dados sensíveis no payload: O JWT é apenas assinado, não criptografado. Qualquer um que decode o Base64URL consegue ler o payload.
  • Blacklist de tokens: Para revogação imediata, mantenha uma blacklist em cache (Redis) de tokens invalidados.

OAuth 2.0 + JWT vs Alternativas

AbordagemStateful?EscalabilidadeQuando usar
OAuth 2.0 + JWTStatelessExcelenteAPIs REST, microsserviços, SSO
Sessão com CookieStatefulLimitadaMonólitos, apps server-render
API KeyStatelessBoaMachine-to-machine, serviços internos
Basic AuthStatelessRuimApenas para testes ou legacy

Ferramentas Populares

  • Auth0: Plataforma completa de autenticação como serviço, com suporte nativo a OAuth 2.0 e JWT.
  • Keycloak: Solução open-source de gerenciamento de identidade e acesso, ideal para self-hosted.
  • NextAuth.js / Auth.js: Biblioteca de autenticação para Next.js e frameworks modernos.
  • Passport.js: Middleware de autenticação flexível para Node.js com suporte a 500+ estratégias.
  • jsonwebtoken (npm): Biblioteca oficial para criar e verificar JWTs em Node.js.

Conclusão

OAuth 2.0 e JWT formam a espinha dorsal da segurança em APIs modernas. Enquanto o OAuth 2.0 define como o acesso é autorizado — com fluxos bem definidos para cada cenário — o JWT fornece um formato leve, autocontido e seguro para transportar as informações de autenticação.

A combinação dos dois permite construir sistemas stateless e altamente escaláveis, onde qualquer serviço pode validar um token sem precisar consultar um banco de dados central. Isso é essencial em arquiteturas de microsserviços, APIs públicas e sistemas de SSO (Single Sign-On).

Lembre-se: segurança não é um produto, é um processo. Comece com o fluxo correto, aplique as boas práticas e revise sua implementação regularmente. 🚀

Craft XP
Craft XP