1. Go to this page and download the library: Download jekk0/jwt-auth library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
jekk0 / jwt-auth example snippets
// app/Http/Controllers/UserAuthController.php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UserAuthController
{
public function login(Request $request): JsonResponse
{
$credentials = $request->only('email', 'password');
// $tokens = auth('jwt-user')->attempt($credentials);
// if (is_null($tokens)) {
// throw new AuthenticationException();
// }
$tokens = auth('jwt-user')->attemptOrFail($credentials);
return new JsonResponse($tokens->toArray());
}
public function refresh(Request $request): JsonResponse
{
$tokens = auth('jwt-user')->refreshTokens((string)$request->get('token'));
return new JsonResponse($tokens->toArray());
}
public function logout(): JsonResponse
{
auth('jwt-user')->logout();
return new JsonResponse();
}
public function logoutFromAllDevices(): JsonResponse
{
auth('jwt-user')->logoutFromAllDevices();
return new JsonResponse();
}
public function profile(Request $request): JsonResponse
{
return new JsonResponse(['name' => $request->user()->name, 'email' => $request->user()->email]);
}
}
// routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserAuthController;
Route::group(['prefix' => '/auth/user'], function () {
Route::post('/login', [UserAuthController::class, 'login']);
Route::post('/refresh', [UserAuthController::class, 'refresh']);
Route::post('/logout', [UserAuthController::class, 'logout'])->middleware('auth:jwt-user');
Route::post('/logout/all', [UserAuthController::class, 'logoutFromAllDevices'])->middleware('auth:jwt-user');
Route::get('/profile', [UserAuthController::class, 'profile'])->middleware('auth:jwt-user');
});
// routes/console.php
use Illuminate\Support\Facades\Schedule;
use Jekk0\JwtAuth\Model\JwtRefreshToken;
Schedule::command('model:prune', ['--model' => [JwtRefreshToken::class]])->daily();
php artisan make:listener AccessTokenInvalidation
namespace App\Listeners;
use Illuminate\Auth\AuthenticationException;
use Jekk0\JwtAuth\Events\JwtAccessTokenDecoded;
use Jekk0\JwtAuth\Model\JwtRefreshToken;
class AccessTokenInvalidation
{
public function handle(JwtAccessTokenDecoded $event): void
{
// Solution 1
$accessTokenId = $event->accessToken->payload->getJwtId();
$refreshToken = JwtRefreshToken::whereAccessTokenJti($accessTokenId)->first();
if ($refreshToken === null) {
throw new AuthenticationException();
}
// Solution 2
// $refreshTokenId = $event->accessToken->payload->getReferenceTokenId();
// $refreshToken = JwtRefreshToken::find($refreshTokenId);
//
// if ($refreshToken === null) {
// throw new AuthenticationException();
// }
// Solution 3
// If you do not want to use a relational database, you can implement token invalidation using two events:
// 1. On Logout (JwtLogout Event) – Store the access token in a blacklist for its remaining lifetime using a fast storage solution, such as Redis or MongoDB.
// 2. On Token Decoding (JwtAccessTokenDecoded Event) – Check whether the token is in the blacklist before processing it.
}
}
php artisan make:listener RefreshTokenCompromised
namespace App\Listeners;
use Illuminate\Support\Facades\Log;
use Jekk0\JwtAuth\Events\JwtRefreshTokenCompromised;
use Jekk0\JwtAuth\Model\JwtRefreshToken;
class RefreshTokenCompromised
{
public function handle(JwtRefreshTokenCompromised $event): void
{
Log::info("Guard $event->guard: Refresh token compromised.");
// Get all user refresh tokens
$affectedRefreshTokens = JwtRefreshToken::where('subject', '=', (string)$event->user->id)->get();
// If you use Access token invalidation then this step is not needed
foreach ($affectedRefreshTokens as $refreshToken) {
$accessTokenId = $refreshToken->access_token_jti;
// Invalidate access tokens
// ...
}
// Invalidate refresh tokens related to user
JwtRefreshToken::whereIn('jti', $affectedRefreshTokens->pluck('jti'))->delete();
// Send notification to user
//...
}
}
// file app/Models/User.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Jekk0\JwtAuth\Contracts\CustomClaims;
class User extends Authenticatable implements CustomClaims
{
// ...
public function getJwtCustomClaims(): array
{
return [
'role' => 'user',
'name' => 'John'
];
}
}
//...
// Get custom claims in controller
$role = auth('jwt-user')->getAccessToken()->payload['role']
$name = auth('jwt-user')->getAccessToken()->payload['name']
// file /app/Providers/CustomJwtTokenExtractor.php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Jekk0\JwtAuth\Contracts\TokenExtractor;
class CustomJwtTokenExtractor extends ServiceProvider
{
public function register(): void
{
$this->app->bind(TokenExtractor::class, function () {
return new class implements TokenExtractor {
public function __invoke(Request $request): ?string
{
return $request->header('X-API-TOKEN');
}
};
});
}
public function boot(): void
{
//
}
}
// file /app/Providers/CustomJwtTokenIssuer.php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Jekk0\JwtAuth\Contracts\TokenIssuer;
class CustomJwtTokenIssuer extends ServiceProvider
{
public function register(): void
{
$this->app->bind(TokenIssuer::class, function () {
return new class implements TokenIssuer {
public function __invoke(Request $request): string
{
return 'CustomIssuer';
}
};
});
}
public function boot(): void
{
//
}
}
public function test_authenticate_in_tests(): void
{
$user = UserFactory::new()->create();
$response = $this->actingAs($user, 'YOUR-GUARD-NAME')->postJson('/api/profile');
self::assertSame(200, $response->getStatusCode());
}
public function test_logout(): void
{
$user = UserFactory::new()->create();
auth('user')->login($user);
$response = $this->postJson('/api/logout');
self::assertSame(200, $response->getStatusCode());
}