How does Laravel sanctum expire tokens?
Asked Answered
M

4

18

When I run $user->currentAccessToken()->delete(); the token expires, Auth::check() becomes false, what it is expected.

However, when I go to the personal_access_tokens table, the token is still there. There is no soft delete field. How does Sanctum now that the token is expired?

Menswear answered 29/9, 2020 at 9:47 Comment(2)
sanctum.php inside 'expiration' => null, you can setCutcheon
@KamleshPaul, yes, but that's based on the creation time, not in the last time used, which is not ideal. What's the point on having a 1 day expiration token if the user is continously using the app? Not a good user experience if you are using it and suddently gets log outMenswear
N
30

You can set in config/sanctum.php array node expiration

/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/

'expiration' => 60 * 24 * 7,
Ne answered 2/2, 2021 at 10:29 Comment(0)
K
9

As of writing this answer, the token now deletes from the database so that one is settled.

How Sanctum knows if a token is expired is pretty simple:

  • The token has a created date, call it C
  • The config data in config/sanctum.php has an expiration time, call it E
  • The current time you want to use the token is right now, call it N

To check for expiry, it subtracts N from C. If N - C is less than E, the token hasn't expired yet. If it is greater, the token is expired.

Example:

  • You created a token at 5:00 AM
  • The expiration time is set for 5 hours
  • You want to access data through the token at 8:00 AM

When you subtract 8 from 5, you get 3. That's just 3 hrs since you created the token. Not up to the 5 hrs you set.

If you were accessing data at say, 11:00 AM, then the time frame becomes 6 hrs, which is more than 5 hrs, meaning the token has expired.

Kinsman answered 14/8, 2021 at 16:9 Comment(2)
i proven that this method is correct. But would it be possible to use the last_used_at to be the 'C'. In that case if the token have been stale for 'E' minutes then it would be considered as expired.Formidable
it is possible, but you would have to implement that manually. you can start by looking at the tokens table (personal_access_tokens) and use your logic and DB queries to achieve your goalsKinsman
V
4

I looked in the source code of sanctumm and it seems like it's a guard that handles it.

      if (! $accessToken ||
                ($this->expiration &&
                 $accessToken->created_at->lte(now()->subMinutes($this->expiration))) ||
                ! $this->hasValidProvider($accessToken->tokenable)) {
                return;
            }

This means that the validating token proccess looks like this:

  • Check if token is present in database
  • Check if token creation_date hasnt surpassed the expiration time
  • Check if the tokenable model matches the provider's model type
  • Check if the tokenable model supports API tokens

And upon fail, it's simply rejecting the request. Not deleting the token.

Deleting the token is however the manual way to revoke a token.

You may "revoke" tokens by deleting them from your database using the tokens relationship that is provided by the HasApiTokens trait:

Vauban answered 29/9, 2020 at 10:8 Comment(8)
Thanks! but that's the thing, when I do $user->currentAccessToken()->delete(); it does revoke the token, but it doesn't get deleted from the database. I guess my question is, how does Sanctum know that the token has expired?Menswear
@InigoEC I thought that was the question that I answered, Sanctum doesn't modify the token in anyway, but rejects the request when its expired. The reason for your delete method to not work is most likely some misconfiguration. Have you added the trait HasApiTokens in user model?Vauban
Hi @PatricNox, so how does Sanctum check that it's expired? Assuming that the expiration is null in the sanctum config file and I manually expire it using $user->currentAccessToken()->delete();; There is nothing like "expired_at" in the DBMenswear
@InigoEC If you remove the token, it's handled as a revoked token. Otherwise, the record will be there even though it has expired, by default. Sanctum compares expiration time against the created_at field, not expired_atVauban
Where is the expiration time defined?Sandrasandro
@Sandrasandro The expiration time is defined in your config file for Sanctum. ./config/santum.phpVauban
@Vauban Hi, I have set the expiration to 1800 from /config/sanctum.php/ but its still empty in the database, I think it's for a migration file that accepts nullable too, but if I remove nullable from there, the process of running the command for migrating and seeding of tables throws an error that filed can not be null, so what should I do?Calefactory
@Calefactory sounds like a $fillable thingVauban
N
3

The code below would only return a token as valid if its last_used_at is greater than or equal to 72 hours. Just put this inside the AppServiceProvider & change the 72 to reflect the number of hours of inactivity you want it to react to.

use Laravel\Sanctum\Sanctum;
Sanctum::$accessTokenAuthenticationCallback = function ($accessToken, $isValid){
        return !$accessToken->last_used_at || $accessToken->last_used_at->gte(now()->subHours(72));
    };
Nomo answered 8/3, 2023 at 4:52 Comment(1)
Thankyou Bro! This works like Charm!❤Shannan

© 2022 - 2025 — McMap. All rights reserved.