JWT Tokens in PHP: Complete Implementation Guide
JWT (JSON Web Token) is an open standard (RFC 7519) for creating access tokens based on JSON format. In PHP, JWT is widely used for implementing stateless authentication in REST APIs, single-page applications (SPA), and microservices.
In this article, we will thoroughly examine how to work with JWT tokens in PHP: from library installation to creating, verifying, and refreshing tokens.
What is JWT and Why is it Needed?
JWT consists of three parts separated by dots:
- Header — contains the token type (JWT) and the signing algorithm (e.g., HS256 or RS256).
- Payload — contains claims: user identifier, role, issued at time (iat), expiration time (exp), and other data.
- Signature — created by hashing the header and payload using a secret key.
Main advantages of JWT:
- Does not require storing sessions on the server (stateless).
- Can contain any data (e.g., user role).
- Works across different domains and mobile applications.
- Easily verifiable without database queries.
Installing the firebase/php-jwt Library
To work with JWT in PHP, we will use the popular library firebase/php-jwt. Installation is done via Composer:
composer require firebase/php-jwtAfter installation, the Composer autoloader will be available in the project and needs to be included:
require_once 'vendor/autoload.php';
use Firebase\\JWT\\JWT;use Firebase\\JWT\\Key;Creating a JWT Token
To create a token, you need to define a secret key ($secretKey) and form the payload. Example:
use Firebase\\JWT\\JWT;
$secretKey = 'your-256-bit-secret-key-here';$issuedAt = time();$expirationTime = $issuedAt + 3600; // token lives for 1 hour
$payload = [ 'iss' => 'pythonlib.ru', // issuer 'iat' => $issuedAt, // issued at 'exp' => $expirationTime, // expiration time 'sub' => 123, // user identifier 'role' => 'admin' // custom data];
$jwt = JWT::encode($payload, $secretKey, 'HS256');echo $jwt;The result will be a string like: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJweXRob25saWIucnUiLCJpYXQiOjE3Mjg0MDAwMDAsImV4cCI6MTcyODQwMzYwMCwic3ViIjoxMjMsInJvbGUiOiJhZG1pbiJ9.signature
Verifying and Decoding JWT
When receiving a token from the client (e.g., from the Authorization: Bearer <token> header), it needs to be verified:
use Firebase\\JWT\\JWT;use Firebase\\JWT\\Key;
$secretKey = 'your-256-bit-secret-key-here';$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); $userId = $decoded->sub; $role = $decoded->role; echo "User #{$userId} with role {$role} is authorized.";} catch (\\Exception $e) { http_response_code(401); echo "Error: " . $e->getMessage();}Important: the library automatically checks the token expiration time (exp) and issued at time (iat). If the token is expired or invalid, an exception will be thrown.
Token Refresh (Refresh Token)
To enhance security, JWT tokens are typically made short-lived (15–60 minutes). For long sessions, a Refresh Token is used — a separate token stored in the database that allows obtaining a new Access Token without re-entering login/password.
Example of refresh implementation:
function refreshAccessToken(string $ref Also in library
Kotlin Task Scheduler: Overview and Usage Examples
PHP Application Configuration: Libraries and Tools for Settings Management