sanctum-refresh
sanctum-refresh copied to clipboard
A full featured sanctum api with refresh token and expiration.
Sanctum Refresh
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
POSTmethod.
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::classThe
LoginRequestprovideauth()method to help you authenticate the user by eitherusernameoremailand finallypassword. -
CheckForRefreshToken:
It is unnecessary for you to use
CheckRefreshTokenif 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
$refreshTokenas a string and you're set. The Helpers will take care validating the entire thing for you and returntrueif success, throw:Albet\SanctumRefresh\Exceptions\InvalidTokenException::classif 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
CheckRefreshTokenmiddleware 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
PersonalAccessTokenModel. 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
HasApiTokenfrom Sanctum.- HasRefreshable Trait (PersonalAccessToken extension)
Sanctum Refresh also provide:
Albet\SanctumRefresh\Traits\HasRefreshable::classAbove trait will inject relationship to your custom
PersonalAccessTokenmodel. -
TokenIssuer
Just like before, SanctumRefresh also provide
TokenIssuer:Albet\SanctumRefresh\Services\TokenIssuer::classThis 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
Collectioninstance 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
$modelover and over inTokenIssuer. You can just useHasRefreshableTokentrait 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$idmust 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.