Custom Access Tokens in Laravel Sanctum
source link: https://doeken.org/blog/custom-access-tokens-laravel-sanctum
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Custom Access Tokens in Laravel Sanctum
Create single-use access tokens and more
- Laravel Sanctum
- Laravel
- PHP
I recently had a Laravel project in which I wanted a simple access token to protect an API; and Laravel Sanctum is a package that provides exactly that. However, by default, this package had a bit of a shotgun approach for validating these access tokens. You could either:
- Let every token live forever (default behavior)
- Make every token expire after a certain amount of minutes
Since there was no middle ground I created a PR that allowed for more control over these validation rules. This PR has since been released in Laravel Sanctum 2.11.0.
Let's have a look at how you can build your own custom validation rules.
Registering a custom validation with Sanctum
To register a custom validation we can instruct Sanctum to use a callable
via the
Sanctum::authenticateAccessTokensUsing()
method. You should call this method in the boot()
method of one of your
service providers. The callable
will contain your custom logic, and will typically be:
- A callback function
- An
__invoke
-able class - A (method on a) service from the IoC container
In these examples we'll use a callback function, and register them in the AppServiceProvider::boot()
method.
use Laravel\Sanctum\PersonalAccessToken;
use Laravel\Sanctum\Sanctum;
class AppServiceProvider
{
// ...
public function boot()
{
// ...
Sanctum::authenticateAccessTokensUsing(
static function (PersonalAccessToken $accessToken, bool $is_valid) {
// Your custom logic goes here
}
);
}
}
As you can see, the callable
receives the provided access token model instance, as well as a boolean
indicating
whether the Guard
from Sanctum deemed this token valid.
Tip: If the
Guard
could not find the provided access token, the callback method will not be triggered. So ourcallable
will always receive an instance of the provided access token.Tip 2: The access token model does not have to be an instance of
PersonalAccessToken
, because you can set a different model by using theSanctum::usePersonalAccessTokenModel()
method.
Now that we can add our own validation, let's look at a couple of useful examples.
Single-use access tokens
You might want to provide an access token that can be used only once and has a limited scope. So lets say, when our
token has a read:once
ability, we only want this token to be used once.
Sanctum::authenticateAccessTokensUsing(
static function (PersonalAccessToken $accessToken, bool $is_valid) {
if (!$accessToken->can('read:once')) {
return $is_valid; // We keep the current validation.
}
return $is_valid && $accessToken->last_used_at === null;
}
);
After making sure the token has the read:once
ability, the callback does two simpel checks:
- Does Sanctum deem this token valid?
- Is the
last_used_at
value still empty (indicating it has not been used yet)?
If both of these checks pass, the token is valid. Otherwise, it was already invalid, or it has been used before.
To hand out these tokens, you can create them like this:
return $user->createToken('token-name', ['read:once'])->plainTextToken;
Short-lived tokens with variable lifetimes
Obviously you can already create short-lived tokens in Sanctum by default; the only drawback is that every token has to be short-lived. However, we can now create short-lived tokens while also using limitless tokens.
Using the same approach as before, we are going to create a token with a read:limited
ability. Those tokens are
allowed to be used for 30 minutes.
Sanctum::authenticateAccessTokensUsing(
static function (PersonalAccessToken $accessToken, bool $is_valid) {
if (!$accessToken->can('read:limited')) {
return $is_valid;
}
return $is_valid && $accessToken->created_at->gt(now()->subMinutes(30));
}
);
We're doing almost the same check, but now we make sure our token was created within the last 30 minutes. Otherwise, it isn't valid.
Endless possibilities
These two examples are very simple, but the possibilities for (re)validating your access tokens are almost limitless
now. I would recommend using a dedicated class for these rules to keep your boot()
method clean.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK