albetnov / sanctum-refresh
This package extends sanctum ability to be able to provide refresh token as well
Requires
- php: ^8.1
- illuminate/contracts: ^9.0
- laravel/sanctum: ^3.2
- nesbot/carbon: ^2.65
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2024-10-24 16:43:45 UTC
README
A Package to extend Sanctum to have refresh token as well.
Installation
You can install the package via composer:
composer require albetnov/sanctum-refresh
Then you'll need to push and run the migration with:
php artisan vendor:publish --tag="sanctum-refresh-migrations"
php artisan migrate
You 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 ], /** * Configuration of Sanctum Refresh behaviour */ 'sanctum_refresh' => [ /** * Custom the api response message * array<string, string> */ 'message' => [ // Authenticated successful message to be used by /login route 'authed' => 'Authentication success!', // Invalid or expired refresh token message 'invalidMsg' => 'Refresh token is expired or invalid.', ], /** * Custom the routes behaviour * array<string, string> */ 'routes' => [ // Only show refresh route (hide the login route) 'refreshOnly' => false, /** * Custom the routes urls * array<string, string> */ 'urls' => [ 'login' => '/login', 'refresh' => '/refresh', ], /** * Custom the routes middlewares * array<string, ?array> */ 'middlewares' => [ 'login' => null, 'refresh' => ['checkRefreshToken'], ], ], ], ];
Quick Start
The easiest way to start with this package are using the provided scaffold.
First, install the provided Middleware at App\Http\Kernel
in $routeMiddleware
by adding:
'checkRefreshToken' => Albet\SanctumRefresh\Middleware\CheckRefreshToken
Then register the routes by putting code above in any service providers. E.g. AuthServiceProvider
:
SanctumRefresh::routes();
After that the routes should be accessible with given config urls. E.g. /login
, /refresh
. Or you can just
look into it by performing:
php artisan route:list
The routes will also register under the name login
and refresh
assuming you put the routes not inside a
grouping with name prefix.
The login
routes accepts username
or email
as user identifier and takes password
for the password.
In the other hand the refresh
routes accepts neither refresh_token
cookie or refresh_token
json body.
Both of the above urls are accessible with
POST
method.
Going Manual
Sanctum Refresh make it easy and painless for you to for performing an manual integration with your project and this package.
-
Auth Scaffolding:
Sanctum Refresh provide an auth scaffold. This scaffold can be used for your custom controllers.
Albet\SanctumRefresh\Requests\LoginRequest::class
The
LoginRequest
provideauth()
method to help you authenticate the user by eitherusername
oremail
and finallypassword
. -
CheckForRefreshToken:
It is unnecessary for you to use
CheckRefreshToken
if you don't want to. For instance, you may need to modify on how the middleware will take Refresh Token. You can achieve this will minimal code using the provided:Albet\SanctumRefresh\Helpers\CheckForRefreshToken::check($refreshToken);
Simply pass the
$refreshToken
as a string and you're set. The Helpers will take care validating the entire thing for you and returntrue
if success, throw:Albet\SanctumRefresh\Exceptions\InvalidTokenException::class
if fails. An example usage (CheckRefreshToken middleware):
// Check refresh token. $refreshToken = $request->hasCookie('refresh_token') ? $request->cookie('refresh_token') : $request->get('refresh_token'); if (! $refreshToken) { return response()->json([ 'message' => SanctumRefresh::$middlewareMsg, ], 400); } try { CheckForRefreshToken::check($refreshToken); return $next($request); } catch (InvalidTokenException $e) { return response()->json([ 'message' => SanctumRefresh::$middlewareMsg, 'reason' => $e->getMessage(), ], 400); }
Above is
CheckRefreshToken
middleware code. -
Custom PersonalAccessToken Model
Since version 2. Sanctum Refresh no longer overriding any codes from Sanctum. Instead, this package wraps around it. With that being said, You're now free to modify whatever you want with the
PersonalAccessToken
Model. This is important if you want to use this package in a already exist project. Simply put:use Custom\Models\PersonalAccessToken; Albet\SanctumRefresh\SanctumRefresh::usePersonalAccessTokenModel(PersonalAccessToken::class);
In any service provides. The model though must extend
HasApiToken
from Sanctum.- HasRefreshable Trait (PersonalAccessToken extension)
Sanctum Refresh also provide:
Albet\SanctumRefresh\Traits\HasRefreshable::class
Above trait will inject relationship to your custom
PersonalAccessToken
model. -
TokenIssuer
Just like before, SanctumRefresh also provide
TokenIssuer
:Albet\SanctumRefresh\Services\TokenIssuer::class
This class contains two methods:
Albet\SanctumRefresh\Services\TokenIssuer::issue($model, $name, $config)
Above method will generate a token complete with refresh token. The method takes 3 arguments. The Tokenable Model, token name, and finally config (expiration, etc).
Albet\SanctumRefresh\Services\TokenIssuer::refreshToken($refreshToken, $name, $config)
Above method will regenerate a token. But instead of based on Tokenable Model. This method will regenerate the token based on given Refresh Token. This method takes 3 arguments. The plain refresh token string, the new token name, and config (expiration, etc).
Both methods above return
Collection
instance with entry like below:[ accessTokenInstance, refreshTokenInstance, plain => [accessToken, refreshToken] ]
Sanctum Refresh also provide
config_builder()
to generate a config arrays with more easy to read. Example usage:TokenIssuer::refreshToken($string, $name, config_builder( abilities: ['*'], tokenExpiresAt: now()->addSeconds(30), refreshTokenExpiresAt: now()->addHour() ))
-
HasRefreshableToken Trait (User Model)
Instead of having pain putting
$model
over and over inTokenIssuer
. You can just useHasRefreshableToken
trait in your user model:<?php use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Laravel\Sanctum\HasApiTokens; use Albet\SanctumRefresh\Traits\HasRefreshableToken; class User extends Model { use HasApiTokens, HasFactory, HasRefreshableToken; ...
Above is the example of your final User model will look like.
This trait will provide you with 2 methods.
-
createTokenWithRefresh($name, $config)
Create an access token as well as refresh token. A wrapper around
TokenIssuer::issue()
without$model
. -
revokeBothTokens()
Revoke both access token and refresh token.
-
-
RefreshTokenRepository
Finally, Sanctum Refresh also provide you a repository. As it's name suggest. This repository will help you with Revoking Refresh Token (Without revoking the access token). This repository provides you with 2 methods.
-
Revoke refresh token from given id
revokeRefreshTokenFromTokenId($id)
will revoke / delete the refresh token from given$id
. This$id
must be an id of RefreshToken table. -
Revoke refresh token from plain token
revokeRefreshTokenFromToken($stringToken)
will revoke / delete the refresh token from given plain token.
-
That's all!
Testing
Run the tests:
composer test
Figure out the code coverage:
composer test-coverage
Changelog
Please see Changelog for more information.
Contributing
You are free to contribute to this project.
Credits
License
The MIT License (MIT). Please see License File for more information.