Minimal and flexible package to extend Sanctum to have refresh token as well.
You can install the package via composer:
composer require albetnov/sanctum-refreshThen you'll need to push and run the migration with:
php artisan vendor:publish --tag="sanctum-refresh-migrations"
php artisan migrateYou can also publish the config file with:
php artisan vendor:publish --tag="sanctum-refresh-config"This is the contents of the published config file:
return [
/**
* Set the fallback expiration time of both tokens
* Time in minutes.
*/
'expiration' => [
// set the fallback of access token expiration
'access_token' => 2, // 2 minutes,
// set the fallback of refresh token expiration
'refresh_token' => 30, // 30 minutes
],
];<?php
namespace App\Http\Controllers;
use Albet\SanctumRefresh\Services\TokenIssuer;
class TokenController {
function newToken() {
$token = TokenIssuer::issue($request->user(), guard: 'api');
return response()->json([
'message' => 'Token generated successfully!',
'data' => $token->toArray(),
]);
}
}Response schema:
{
"message": "Token generated successfully!",
"data": {
"access_token": "[string]",
"access_token_expires_at": "[Y-m-d H:i:s]",
"refresh_token": "[string]",
"refresh_token_expires_at": "[Y-m-d H:i:s]"
}
}Refresh Token Middleware (optional, if you want to customize error based on expired, invalid format, etc)
<?php
// (...)
use Albet\SanctumRefresh\Helpers;
use Albet\SanctumRefresh\Exceptions\SanctumRefreshException;
class TokenMiddleware {
public function handle(Request $request, \Closure $next): Response {
try {
Helpers::getRefreshToken(
$request->get('refresh_token', '') // adjust to your liking, either from Query Parameter, Body, or Header.
);
return $next($request);
} catch (SanctumRefreshException $e) {
// handle tags of SanctumRefreshException
return response()->json([
'error' => 'Refresh token invalid'
], 400);
}
}
}<?php
// imports...
Route::post('refresh-token', [TokenController::class, 'refreshToken'])->middleware(TokenMiddleware::class);<?php
use Albet\SanctumRefresh\Services\TokenIssuer;
class TokenController {
public function refreshToken(Request $request) {
$newToken = TokenIssuer::refreshToken($request->get('refresh-token', ''));
if(!$newToken) {
return response()->json([
'error' => 'Refresh token not valid',
], 400);
}
return response()->json([
'message' => 'New token created',
'data' => $newToken->toArray(),
]);
}
}Register prune:token on your commands Kernel.php, you can run it as cron job:
Schedule::command('prune:token')->daily();Run the tests:
composer testFigure out the code coverage:
composer test-coverageLocal composer test runs replay via Pest's Test Impact Analysis, skipping unaffected tests, when pcov or Xdebug (coverage mode) is installed. It's inert without one, and always off in CI.
Please see Changelog for more information.
You are free to contribute to this project.
The MIT License (MIT). Please see License File for more information.