adhocore/jwt
Lightweight PHP JWT library with simple encode/decode APIs, support for common algorithms (HS/RS), claims validation, and key handling. Designed for quick integration in apps and APIs with minimal dependencies and clear error reporting.
Installation:
composer require adhocore/jwt
No additional dependencies or complex configurations are required.
First Use Case: Generate a JWT token with default settings:
use Adhocore\Jwt\Jwt;
$jwt = new Jwt();
$token = $jwt->encode(['user_id' => 123], 'your-secret-key');
echo $token; // Outputs a JWT string
Where to Look First:
Jwt class methods: encode(), decode(), verify(), and getPayload().Token Generation:
$jwt = new Jwt();
$token = $jwt->encode(
['user_id' => 123, 'role' => 'admin'],
'your-secret-key',
['alg' => 'HS256', 'typ' => 'JWT'] // Optional headers
);
HS256 (HMAC-SHA256) for symmetric signing (common for APIs).RS256), pass a private key as the second argument and use encodeWithKey().Token Verification/Decoding:
$jwt = new Jwt();
$payload = $jwt->decode($token, 'your-secret-key');
// Or verify first (throws exception on failure):
$jwt->verify($token, 'your-secret-key');
$payload = $jwt->getPayload();
Middleware Integration (Laravel):
// app/Http/Middleware/VerifyJwt.php
public function handle($request, Closure $next) {
$jwt = new Jwt();
try {
$jwt->verify($request->bearerToken(), config('jwt.secret'));
$request->merge(['user' => $jwt->getPayload()]);
} catch (\Exception $e) {
abort(401, 'Invalid token');
}
return $next($request);
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\VerifyJwt::class,
];
Custom Claims: Add metadata to payloads for business logic:
$token = $jwt->encode([
'user_id' => 123,
'exp' => time() + 3600, // Expiry (Unix timestamp)
'custom_claim' => 'value'
], 'secret');
Token Expiry Handling:
// Set expiry in payload (seconds from now)
$payload = ['user_id' => 123, 'exp' => time() + 3600];
$token = $jwt->encode($payload, 'secret');
// Decode and check expiry manually
$decoded = $jwt->decode($token, 'secret');
if (isset($decoded['exp']) && $decoded['exp'] < time()) {
throw new \Exception('Token expired');
}
Secret Key Management:
.env:
JWT_SECRET=your-strong-secret-key-here
Algorithm Assumptions:
HS256 if no algorithm is specified. Always explicitly set the algorithm to avoid ambiguity:
$token = $jwt->encode($payload, 'secret', ['alg' => 'HS256']);
Payload Size Limits:
Time Skew:
exp claims:
$payload['exp'] = time() + (3600 + 300); // 1 hour + 5 min buffer
Error Handling:
decode() and verify() throw exceptions on failure. Catch specific exceptions (e.g., Adhocore\Jwt\Exception\InvalidToken) for granular error handling:
try {
$jwt->verify($token, 'secret');
} catch (\Adhocore\Jwt\Exception\InvalidToken $e) {
// Handle invalid token
}
Token Inspection: Use jwt.io to decode and inspect tokens manually for debugging.
Logging: Log payloads and tokens (sanitized) for auditing:
\Log::debug('JWT Payload', ['payload' => $jwt->getPayload()]);
Testing:
Mock the Jwt class in PHPUnit for isolated testing:
$mockJwt = $this->createMock(Jwt::class);
$mockJwt->method('decode')->willReturn(['user_id' => 123]);
Custom Algorithms:
Extend the library by implementing your own algorithm handler (advanced). The library supports HS256, HS384, HS512, RS256, RS384, and RS512 out of the box.
Payload Validation: Add validation logic post-decoding:
$payload = $jwt->decode($token, 'secret');
if (!in_array($payload['role'], ['admin', 'editor'])) {
throw new \Exception('Insufficient permissions');
}
Token Storage:
For stateless APIs, store tokens in HTTP-only cookies or Authorization: Bearer headers. Avoid localStorage for security.
Refresh Tokens: Implement a refresh token workflow:
// Issue a short-lived access token + long-lived refresh token
$accessToken = $jwt->encode(['exp' => time() + 3600], 'access-secret');
$refreshToken = $jwt->encode(['exp' => time() + 86400], 'refresh-secret');
Performance:
Jwt instances (stateless, thread-safe).How can I help you explore Laravel packages today?