Introdução: por que OAuth 2.0 e JWT são necessários em PHP
Aplicações web modernas raramente funcionam isoladamente. Os usuários esperam login único via Google, Facebook ou GitHub, e os desenvolvedores esperam troca segura de dados entre microsserviços. Dois protocolos-chave — OAuth 2.0 (delegação de acesso) e JWT (formato compacto de token) — tornaram-se o padrão de facto. Neste artigo, vamos analisar como implementar autorização OAuth 2.0 e JWT em PHP do zero, usando apenas recursos nativos da linguagem e bibliotecas populares. Você obterá exemplos de código prontos para integração com provedores externos e criação do seu próprio sistema de autenticação.
1. Fundamentos do OAuth 2.0: fluxos e papéis
OAuth 2.0 é um protocolo de autorização que permite que aplicativos de terceiros obtenham acesso limitado aos recursos do usuário sem transmitir a senha. Ele envolve quatro papéis:
- Resource Owner — o usuário que possui os dados.
- Client — sua aplicação PHP que solicita acesso.
- Authorization Server — servidor que emite tokens (ex.: Google).
- Resource Server — API que fornece dados com base no token.
O fluxo mais popular para aplicações web é o Authorization Code Grant. Ele é seguro porque o token é transmitido pelo lado do servidor, não pelo navegador. Vamos analisar a implementação em PHP.
1.1. Registro da aplicação e obtenção de Client ID/Secret
Antes de escrever o código, registre a aplicação no provedor (ex.: no Google Cloud Console). Você receberá client_id e client_secret, além de configurar o redirect URI (ex.: https://seudominio.com/callback.php).
1.2. Implementação do fluxo Authorization Code em PHP
Vamos criar dois arquivos: login.php (redirecionamento para o servidor de autorização) e callback.php (processamento da resposta).
Arquivo login.php
<?phpsession_start();
$client_id = 'SEU_CLIENT_ID';$redirect_uri = 'https://seudominio.com/callback.php';$state = bin2hex(random_bytes(16)); // proteção contra CSRF$_SESSION['oauth_state'] = $state;
$params = http_build_query([ 'client_id' => $client_id, 'redirect_uri' => $redirect_uri, 'response_type' => 'code', 'scope' => 'openid email profile', 'state' => $state,]);
header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params);exit;?>Arquivo callback.php
<?phpsession_start();
// Verificação do state (CSRF)if ($_GET['state'] !== $_SESSION['oauth_state']) { die('Erro: state inválido');}
$client_id = 'SEU_CLIENT_ID';$client_secret = 'SEU_CLIENT_SECRET';$redirect_uri = 'https://seudominio.com/callback.php';
// Troca do código pelo token$ch = curl_init('https://oauth2.googleapis.com/token');curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'code' => $_GET['code'], 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'grant_type' => 'authorization_code',]));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);curl_close($ch);
$data = json_decode($response, true);$access_token = $data['access_token'] ?? null;
// Obtenção do perfil do usuário$ch = curl_init('https://www.googleapis.com/oauth2/v2/userinfo');curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$userInfo = json_decode(curl_exec($ch), true);curl_close($ch);
echo 'Olá, ' . htmlspecialchars($userInfo['email']);?>Importante: Sempre verifique o parâmetro state. Ele protege contra falsificação de requisição (CSRF).