How Do You Generate And Validate A JWT
How Do You Generate And Validate A JWT
5.0 out of 5 based on 432 ratings
How Do You Generate and Validate a JWT?
JSON Web Token (JWT) is a compact and secure method for transmitting information between parties as a JSON object. It is commonly used for authentication and authorization in web applications, allowing users to access protected resources without repeatedly providing credentials. Key features include:
- Stateless Authentication: Stores user information in a token, reducing the need for server-side session storage.
- Secure Data Exchange: Uses digital signatures to verify that the token has not been altered.
- Compact Format: Consists of three parts—Header, Payload, and Signature—encoded into a single string.
- Widely Supported: Works across different programming languages and platforms.
JWT Structure
A JWT consists of three parts separated by dots (.):
Header.Payload.SignatureExample JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6IkFkbWluIiwiZXhwIjoxNzYwMDAwMDAwfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c1. Header
The header contains metadata about the token, including the signing algorithm and token type.
{
"alg": "HS256",
"typ": "JWT"
}- alg – Signing algorithm (e.g., HS256, RS256)
- typ – Token type (JWT)
2. Payload
The payload contains claims, which are pieces of information about the user or token.
{
"sub": "1234567890",
"name": "John Doe",
"email": "john@example.com",
"role": "Admin",
"iat": 1751712000,
"exp": 1751715600
}Common claims include:
sub– Subject (User ID)name– User nameemail– User emailrole– User roleiat– Issued at timeexp– Expiration time
3. Signature
The signature verifies that the token has not been altered.
For the HS256 algorithm, the signature is generated using:
HMACSHA256(
Base64UrlEncode(Header) + "." +
Base64UrlEncode(Payload),
SecretKey
)The server uses the same secret key (or a public key for asymmetric algorithms like RS256) to validate the signature.
How to Generate a JWT
How to Generate a JWT
The general process is:
Step 1: Authenticate the User
Verify the user's credentials from the database.
Step 2: Create the Payload
Include essential claims such as:
- User ID
- Role
- Issued At (iat)
- Expiration Time (exp)
Step 3: Sign the Token
Use a secure secret key (or RSA private key) with algorithms like:
- HS256
- HS384
- HS512
- RS256
Step 4: Return the Token
Send the generated JWT to the client after successful login.
Example response:
{
"access_token":"eyJhbGc...",
"expires_in":3600
}
How to Validate a JWT
How to Validate a JWT
Whenever a client sends a request, the server validates the JWT.
Validation includes:
1. Verify Signature
Ensure the token hasn't been modified.
2. Check Expiration
Reject expired tokens.
3. Verify Issuer
Validate the iss claim.
4. Verify Audience
Ensure the token is intended for your application.
5. Validate Custom Claims
Verify user roles, permissions, tenant IDs, or other business-specific claims.
If every validation succeeds, the request is authenticated.
JWT Authentication Flow
- User logs in.
- Server verifies credentials.
- Server generates a JWT.
- Client stores the token securely.
- Client sends the token in the Authorization header.
- Server validates the token.
- Server returns the requested resource.
Best Practices for JWT Security
- Always use HTTPS.
- Keep token expiration short.
- Store refresh tokens securely.
- Never expose your secret key.
- Use strong signing algorithms such as HS256 or RS256.
- Validate every incoming token.
- Include only necessary information in the payload.
- Rotate signing keys periodically.
- Implement token revocation when required.
Common JWT Errors
- Invalid signature
- Expired token
- Incorrect issuer
- Invalid audience
- Malformed token
- Missing Authorization header
Proper error handling helps improve both security and user experience.
Advantages of JWT
- Stateless authentication
- Scalable for distributed systems
- Compact and URL-safe
- Easy integration with APIs
- Supports cross-platform applications
- Reduces server-side session storage
Installation
composer require firebase/php-jwt1. Generate a JWT (HS256 - Symmetric)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
$secretKey = 'your-super-secret-key-here-make-it-long-and-random'; // Store in .env!
$algorithm = 'HS256';
$payload = [
'iss' => 'https://yourdomain.com', // Issuer
'sub' => 'user123', // Subject (user ID)
'aud' => 'https://yourdomain.com', // Audience
'iat' => time(), // Issued at (Unix timestamp)
'exp' => time() + (3600), // Expiration time (1 hour)
'name' => 'John Doe',
'role' => 'admin'
];
$jwt = JWT::encode($payload, $secretKey, $algorithm);
echo "Generated Token:\n" . $jwt . "\n";2. Validate / Decode a JWT
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
$secretKey = 'your-super-secret-key-here-make-it-long-and-random';
$algorithm = 'HS256';
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
$token = str_replace('Bearer ', '', $token); // Remove "Bearer " prefix if present
try {
$decoded = JWT::decode($token, new Key($secretKey, $algorithm));
// Successfully validated
$payload = (array) $decoded;
echo "Valid Token! Payload:\n";
print_r($payload);
} catch (ExpiredException $e) {
http_response_code(401);
echo json_encode(['error' => 'Token has expired']);
} catch (SignatureInvalidException $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
} catch (\Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token: ' . $e->getMessage()]);
}Using RS256 (Asymmetric – Better for production)
Generate keys (one-time):
openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048
openssl rsa -in private.key -pubout -out public.keyGenerate token (with private key):
$privateKey = file_get_contents(__DIR__ . '/private.key');
$jwt = JWT::encode($payload, $privateKey, 'RS256');Validate token (with public key):
$publicKey = file_get_contents(__DIR__ . '/public.key');
$decoded = JWT::decode($token, new Key($publicKey, 'RS256'));