php-open-source-saver/jwt-auth
Laravel JWT authentication package (fork of tymondesigns/jwt-auth) maintained by PHP Open Source Saver. Provides the same API with a new namespace, easy migration, and adds new features and ongoing support. Full docs available online.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require php-open-source-saver/jwt-auth
Publish the config file:
php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider" --tag=config
Configure Auth Guard:
Update config/auth.php to include the JWT guard:
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
First Use Case: Generate a token for a user in a controller:
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
$user = User::find(1);
$token = JWTAuth::fromUser($user);
return response()->json(['token' => $token]);
Protect Routes:
Use middleware in routes/api.php:
Route::middleware('auth:api')->group(function () {
Route::get('/user', function () {
return response()->json(auth()->user());
});
});
Verify Token in Requests:
Send the token in the Authorization header:
Authorization: Bearer <token>
config/jwt.php for settings like:
secret: Encryption key (generate with php artisan jwt:secret).ttl: Token expiration time (e.g., 60 minutes).refresh_ttl: Refresh token TTL.blacklist_enabled: Enable token blacklisting.$token = JWTAuth::fromUser($user);
$refreshedToken = JWTAuth::refresh($token);
if (!$token = JWTAuth::parseToken()) {
return response()->json(['error' => 'Invalid token'], 401);
}
auth:api middleware for protected routes:
Route::middleware('auth:api')->get('/profile', function () {
return auth()->user();
});
JWTMiddleware:
namespace App\Http\Middleware;
use PHPOpenSourceSaver\JWTAuth\Middleware\GetUserFromToken;
use Closure;
class CustomJWTMiddleware extends GetUserFromToken
{
public function handle($request, Closure $next)
{
if (!$this->auth->check()) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $next($request);
}
}
JWTAuth::invalidate($token);
if (JWTAuth::isBlacklisted($token)) {
return response()->json(['error' => 'Token revoked'], 401);
}
$customClaims = ['role' => 'admin', 'scope' => ['read', 'write']];
$token = JWTAuth::fromUser($user, $customClaims);
$token = JWTAuth::getToken();
$claims = JWTAuth::getPayload($token);
jwt.blacklisted, jwt.refresh):
JWTAuth::event(function ($event) {
if ($event instanceof JWTBlacklistEvent) {
Log::info('Token blacklisted: ' . $event->token);
}
});
config/auth.php:
'guards' => [
'api' => ['driver' => 'jwt', 'provider' => 'users'],
'admin' => ['driver' => 'jwt', 'provider' => 'admins', 'ttl' => 3600],
],
$adminToken = JWTAuth::guard('admin')->fromUser($adminUser);
config/jwt.php:
'cookie' => [
'enabled' => true,
'domain' => null,
'path' => '/',
'secure' => env('APP_ENV') === 'production',
'http_only' => true,
'same_site' => 'lax',
'cookie_key_name' => 'jwt_token', // Custom cookie name
],
return response()->json(['message' => 'Logged in'])
->cookie('jwt_token', $token, $minutes = 60);
JWTAuth in tests:
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeader('Authorization', 'Bearer ' . $token)
->get('/api/protected');
// Example: Hybrid auth flow
if ($request->hasHeader('Authorization')) {
// JWT auth
$token = $request->bearerToken();
if (!$token) return response()->json(['error' => 'Unauthorized'], 401);
JWTAuth::parseToken();
} else {
// Sanctum/Passport auth
$this->authenticateWithSanctum();
}
Route::middleware(['auth:api', 'throttle:60,1'])->get('/api/data', function () {
return response()->json(['data' => '...']);
});
Authorization header:
// config/cors.php
'paths' => ['api/*'],
'allowed_headers' => ['*'],
'allowed_methods' => ['*'],
'exposed_headers' => ['Authorization'],
php artisan octane:start
TokenNotProvidedException or TokenExpiredException.try {
if (!$token = JWTAuth::parseToken()) {
return response()->json(['error' => 'Token not provided'], 401);
}
$user = JWTAuth::authenticate();
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
return response()->json(['error' => 'Token expired'], 401);
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['error' => 'Token invalid'], 401);
}
config/jwt.php.jwt:secret artisan command:
php artisan jwt:secret
JWT_SECRET=your_secure_secret_here
blacklist_enabled is false in config/jwt.php.'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
addMinutes method).composer.json aligns:
"require": {
"nesbot/carbon": "^2.66 || ^3.0"
}
if (JWTAuth::isBlacklisted($token)) {
How can I help you explore Laravel packages today?