Installation
composer require web-token/jwt-checker
Add to composer.json if using a custom package:
"require": {
"web-token/jwt-checker": "^1.0"
}
Basic Usage
use WebToken\JWTChecker\Checker;
$checker = new Checker();
$isValid = $checker->check($jwtString);
First Use Case Validate a JWT in a Laravel middleware:
use WebToken\JWTChecker\Checker;
class AuthenticateJWT
{
public function handle($request, Closure $next)
{
$checker = new Checker();
$token = $request->bearerToken();
if (!$token || !$checker->check($token)) {
return response()->json(['error' => 'Invalid token'], 401);
}
return $next($request);
}
}
Token Validation in Controllers
public function protectedRoute(Request $request)
{
$checker = new Checker();
$token = $request->header('Authorization') ?? '';
if (!$checker->check($token)) {
abort(401, 'Unauthorized');
}
// Proceed with logic
}
Integration with Laravel Auth
Override Laravel’s AuthenticatesUsers trait to use JWT:
use WebToken\JWTChecker\Checker;
public function attemptLogin(Request $request)
{
$checker = new Checker();
$token = $request->input('token');
if ($checker->check($token)) {
$user = $this->getUserFromToken($token); // Custom logic
return $this->authenticate($user);
}
return false;
}
Custom Claims Validation Extend the checker for domain-specific rules:
$checker = new Checker();
$claims = $checker->getClaims($jwtString);
if ($claims['role'] !== 'admin') {
abort(403, 'Forbidden');
}
Token Refresh Logic
$checker = new Checker();
if ($checker->isExpired($jwtString)) {
$newToken = $this->refreshToken($user); // Custom refresh logic
return response()->json(['token' => $newToken]);
}
Batch Validation
$tokens = ['token1', 'token2'];
$validTokens = array_filter($tokens, fn($token) => $checker->check($token));
Token Format Assumptions
The package expects a compact JWT string (e.g., eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...).
Fix: Decode base64 if the token is URL-safe:
$jwtString = strtr(base64_decode($token), '+/', '-_');
Time Zone Sensitivity The checker uses the system’s default time zone. For consistency:
$checker = new Checker();
$checker->setTimeZone('UTC'); // Explicitly set
Silent Failures
check() returns false for any invalid token (malformed, expired, etc.).
Debugging: Use getClaims() to inspect errors:
try {
$claims = $checker->getClaims($jwtString);
} catch (\Exception $e) {
// Log or handle specific errors (e.g., expired, invalid signature)
}
Custom Algorithms
Override the default HS256/RS256 validation:
$checker = new Checker();
$checker->setAlgorithm('ES256'); // Elliptic Curve
Claim-Specific Validation Add pre-check logic:
$claims = $checker->getClaims($jwtString);
if ($claims['exp'] < time() - 3600) { // Hard block old tokens
throw new \RuntimeException('Token too old');
}
Performance
Checker instance (stateless but avoids re-parsing).$checker->getClaims($jwtString); // Returns decoded payload
$checker->setVerbose(true); // Logs detailed validation steps
AppServiceProvider:
$this->app->singleton(Checker::class, fn() => new Checker());
Then inject via constructor:
public function __construct(private Checker $checker) {}
$cacheKey = 'jwt_'.$token;
if (!$claims = cache()->get($cacheKey)) {
$claims = $checker->getClaims($token);
cache()->put($cacheKey, $claims, now()->addMinutes(5));
}
How can I help you explore Laravel packages today?