Como Usar Autenticação JWT e OAuth 2.0 em APIs PHP em Produção Já leu

JWT: Fundamentos e Implementação Prática JWT (JSON Web Token) é um padrão aberto (RFC 7519) para transmissão segura de informações entre partes. Diferente de sessões tradicionais, o JWT é stateless: o servidor não precisa armazenar dados sobre o token. Um JWT consiste em três partes separadas por pontos: header.payload.signature. O header contém o tipo do token e o algoritmo de criptografia. O payload armazena as claims (dados) que você deseja transmitir. A signature garante que o token não foi alterado. Aqui está uma implementação prática usando a biblioteca : Boas Práticas com JWT Sempre use algoritmos assimétricos (RS256) em produção em vez de HS256. Armazene a chave secreta em variáveis de ambiente, nunca no código. Implemente rotação de chaves para aumentar a segurança. Configure um tempo de expiração razoável (15 minutos para access tokens, dias para refresh tokens) e nunca armazene informações sensíveis no payload — ele é apenas codificado, não criptografado. OAuth 2.0: Autenticação Delegada OAuth 2.0 é um

JWT: Fundamentos e Implementação Prática

JWT (JSON Web Token) é um padrão aberto (RFC 7519) para transmissão segura de informações entre partes. Diferente de sessões tradicionais, o JWT é stateless: o servidor não precisa armazenar dados sobre o token. Um JWT consiste em três partes separadas por pontos: header.payload.signature.

O header contém o tipo do token e o algoritmo de criptografia. O payload armazena as claims (dados) que você deseja transmitir. A signature garante que o token não foi alterado. Aqui está uma implementação prática usando a biblioteca firebase/php-jwt:

<?php
require 'vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey = 'sua_chave_secreta_super_segura';

// Gerar um JWT
$issuedAt = new DateTimeImmutable();
$expire = $issuedAt->modify('+1 hour')->getTimestamp();

$payload = [
    'iat'  => $issuedAt->getTimestamp(),
    'exp'  => $expire,
    'iss'  => 'sua_aplicacao',
    'sub'  => 'usuario_123',
    'email' => 'usuario@example.com'
];

$token = JWT::encode($payload, $secretKey, 'HS256');
echo "Token: " . $token . "\n";

// Validar um JWT
try {
    $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
    echo "Usuário: " . $decoded->email . "\n";
} catch (Exception $e) {
    echo "Token inválido: " . $e->getMessage();
}
?>

Boas Práticas com JWT

Sempre use algoritmos assimétricos (RS256) em produção em vez de HS256. Armazene a chave secreta em variáveis de ambiente, nunca no código. Implemente rotação de chaves para aumentar a segurança. Configure um tempo de expiração razoável (15 minutos para access tokens, dias para refresh tokens) e nunca armazene informações sensíveis no payload — ele é apenas codificado, não criptografado.

OAuth 2.0: Autenticação Delegada

OAuth 2.0 é um protocolo de autorização que permite aos usuários autenticar-se em sua aplicação usando contas de terceiros (Google, GitHub, Facebook). Diferente de JWT, que é um formato de token, OAuth 2.0 é um fluxo completo de autenticação com papéis bem definidos: Resource Owner (usuário), Client (sua app), Authorization Server (Google, GitHub) e Resource Server (API protegida).

O fluxo mais comum é o "Authorization Code Flow". O usuário é redirecionado para o provedor OAuth, que valida suas credenciais e retorna um código de autorização. Sua aplicação troca esse código por um access token. Aqui está um exemplo usando Google OAuth com a biblioteca google/apiclient:

<?php
require 'vendor/autoload.php';

$clientId = 'seu_client_id.apps.googleusercontent.com';
$clientSecret = 'sua_client_secret';
$redirectUri = 'https://sua-app.com/oauth-callback';

$client = new Google_Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->setRedirectUri($redirectUri);
$client->addScope('email');
$client->addScope('profile');

// 1. Gerar URL de autenticação
if (!isset($_GET['code'])) {
    $authUrl = $client->createAuthUrl();
    header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
    exit;
}

// 2. Troca do código por token
if (isset($_GET['code'])) {
    $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);

    if (!isset($token['error'])) {
        $client->setAccessToken($token);
        $oauth2 = new Google_Service_Oauth2($client);
        $userInfo = $oauth2->userinfo->get();

        $_SESSION['user_email'] = $userInfo->email;
        $_SESSION['user_name'] = $userInfo->name;

        header('Location: /dashboard');
        exit;
    }
}
?>

Combinando JWT e OAuth 2.0 em APIs

A abordagem ideal é usar OAuth 2.0 para autenticação (permitir login) e JWT para autorização (validar requisições subsequentes). Após o usuário fazer login via OAuth, você emite um JWT que ele usa nas requisições à API. Isso combina a segurança do OAuth com a eficiência do JWT.

Aqui está um exemplo prático de um middleware que valida JWTs em requisições:

<?php
require 'vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JWTMiddleware {
    private $secretKey = 'sua_chave_secreta';

    public function validateToken($request) {
        $authHeader = $request->getHeader('Authorization');

        if (!$authHeader) {
            return ['valid' => false, 'message' => 'Token não fornecido'];
        }

        // Formato: "Bearer token_aqui"
        $parts = explode(' ', $authHeader[0] ?? '');
        if (count($parts) !== 2 || $parts[0] !== 'Bearer') {
            return ['valid' => false, 'message' => 'Formato inválido'];
        }

        try {
            $decoded = JWT::decode($parts[1], new Key($this->secretKey, 'HS256'));
            return ['valid' => true, 'user' => $decoded];
        } catch (Exception $e) {
            return ['valid' => false, 'message' => 'Token expirado ou inválido'];
        }
    }
}

// Uso em um endpoint
$middleware = new JWTMiddleware();
$validation = $middleware->validateToken($_SERVER);

if (!$validation['valid']) {
    http_response_code(401);
    echo json_encode(['error' => $validation['message']]);
    exit;
}

// Token válido, prosseguir
$userId = $validation['user']->sub;
?>

Refresh Tokens

Nunca mantenha access tokens com expiração muito longa. Use refresh tokens, armazenados com segurança (httpOnly cookies), para renovar access tokens expirados. O servidor deve validar o refresh token antes de emitir um novo access token, rejeitando tokens revogados.

Conclusão

JWT é excelente para APIs stateless e aplicações modernas, oferecendo eficiência e escalabilidade. OAuth 2.0 é o padrão para autenticação segura com provedores terceirizados, eliminando a necessidade de armazenar senhas. Combinando ambos, você cria um sistema robusto: OAuth 2.0 autentica o usuário inicialmente, JWT autentica requisições subsequentes. Sempre implemente expiração de tokens, use HTTPS, valide rigorosamente no backend e mantenha secrets fora do controle de versão.

Referências


Artigos relacionados