Tokens JWT em PHP: Guia Completo de Implementação
\n\nJWT (JSON Web Token) é um padrão aberto (RFC 7519) para criar tokens de acesso baseados em formato JSON. Em PHP, o JWT é amplamente utilizado para implementar autenticação sem estado (stateless authentication) em APIs REST, aplicativos de página única (SPA) e microsserviços.
\n\nNeste artigo, vamos detalhar como trabalhar com tokens JWT em PHP: desde a instalação da biblioteca até a criação, verificação e renovação de tokens.
\n\nO que é JWT e por que ele é necessário?
\n\nO JWT consiste em três partes separadas por pontos:
\n\n- \n
- Header (cabeçalho) — contém o tipo de token (JWT) e o algoritmo de assinatura (por exemplo, HS256 ou RS256). \n
- Payload (carga útil) — contém as declarações (claims): identificador do usuário, função, horário de emissão (iat), prazo de validade (exp) e outros dados. \n
- Signature (assinatura) — é criada através do hash do cabeçalho e da carga útil usando uma chave secreta. \n
Principais vantagens do JWT:
\n- \n
- Não requer armazenamento de sessões no servidor (stateless). \n
- Pode conter quaisquer dados (por exemplo, a função do usuário). \n
- Funciona com diferentes domínios e aplicativos móveis. \n
- É facilmente verificado sem consultar o banco de dados. \n
Instalação da biblioteca firebase/php-jwt
\n\nPara trabalhar com JWT em PHP, usaremos a biblioteca popular firebase/php-jwt. A instalação é feita via Composer:
composer require firebase/php-jwt\n\nApós a instalação, o carregamento automático do Composer estará disponível no projeto e deve ser incluído:
\n\nrequire_once 'vendor/autoload.php';\n\nuse Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\nCriação de um token JWT
\n\nPara criar um token, é necessário definir uma chave secreta ($secretKey) e montar o payload. Exemplo:
use Firebase\\JWT\\JWT;\n\n$secretKey = 'sua-chave-secreta-de-256-bits-aqui';\n$issuedAt = time();\n$expirationTime = $issuedAt + 3600; // token válido por 1 hora\n\n$payload = [\n 'iss' => 'pythonlib.ru', // emissor\n 'iat' => $issuedAt, // horário de emissão\n 'exp' => $expirationTime, // prazo de validade\n 'sub' => 123, // identificador do usuário\n 'role' => 'admin' // dados personalizados\n];\n\n$jwt = JWT::encode($payload, $secretKey, 'HS256');\necho $jwt;\n\nO resultado será uma string como: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJweXRob25saWIucnUiLCJpYXQiOjE3Mjg0MDAwMDAsImV4cCI6MTcyODQwMzYwMCwic3ViIjoxMjMsInJvbGUiOiJhZG1pbiJ9.signature
Verificação e decodificação do JWT
\n\nAo receber um token do cliente (por exemplo, do cabeçalho Authorization: Bearer <token>), ele deve ser verificado:
use Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\n$secretKey = 'sua-chave-secreta-de-256-bits-aqui';\n$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';\n\ntry {\n $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));\n $userId = $decoded->sub;\n $role = $decoded->role;\n \n echo "Usuário #{$userId} com função {$role} autorizado.";\n} catch (\\Exception $e) {\n http_response_code(401);\n echo "Erro: " . $e->getMessage();\n}\n\nImportante: a biblioteca verifica automaticamente o prazo de validade do token (exp) e o horário de emissão (iat). Se o token expirou ou é inválido, uma exceção será lançada.
\n\nRenovação do JWT (Refresh Token)
\n\nPara aumentar a segurança, os JWTs geralmente são de curta duração (15–60 minutos). Para sessões longas, utiliza-se o Refresh Token — um token separado armazenado no banco de dados que permite obter um novo Access Token sem reentrar com login/senha.
\n\nExemplo de implementação de refresh:
\n\nfunction refreshAccessToken(string $ref