Laravel Sanctum token expiration based on last usage

Dus*_*san 6 php access-token laravel laravel-sanctum

I have set the sanctum token expiration in the config file, for let's say 24 hours:

/*
|--------------------------------------------------------------------------
| 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' => 24 * 60,
Run Code Online (Sandbox Code Playgroud)

Doing that, my token gets invalid after this period of time. What I would like to do instead, is to check this expiration against the last_used_at attribute of the token.

For better understanding here is a simple example:

  • User logs in at Monday - 9:00 -> a new token is created with an expiration of 24 hours
  • still at Monday - 13:00 he makes a request -> token's last_used_at value is set to this time
  • Now the next day, at Tuesday - 11:00, the user wants to make a request... Validation fails because it is past 24 hours from the token creation. But it is still in the 24 hour window from the last usage.

After some digging in the source files I found the Guard, which does this check.

vendor/laravel/sanctum/src/Guard.php

protected function isValidAccessToken($accessToken): bool
{
    if (! $accessToken) {
        return false;
    }

    $isValid =
        (! $this->expiration || $accessToken->created_at->gt(now()->subMinutes($this->expiration)))
        && $this->hasValidProvider($accessToken->tokenable);

    if (is_callable(Sanctum::$accessTokenAuthenticationCallback)) {
        $isValid = (bool) (Sanctum::$accessTokenAuthenticationCallback)($accessToken, $isValid);
    }

    return $isValid;
}
Run Code Online (Sandbox Code Playgroud)

I think, that changing created_at to last_used_at would do exactly what I need, but the question is how to do it? Of course, I don't want to edit the vendor file.

What I've tried so far:

  • I created a custom middleware which checks the last_used_at value, but in the time the middleware gets called, the value is already set to the current time.
  • I added my custom validation in the AuthServiceProvider to the boot() method, where I did the check against the last_used_at value. This time I get the desired value, but the Guard is executed before this. So first happens the check against the created_at_value from the guard and the token is invalid by the time my custom validation is executed.

sor*_*t72 7

您可以更新圣所守卫:

  1. 忽略密室服务提供商自动发现。转到您的composer.json文件并将Laravel\Sanctum\SanctumServiceProvider添加到dont-discover数组:
"extra": {
    "laravel": {
        "dont-discover": [
            "Laravel\\Sanctum\\SanctumServiceProvider"
        ]
    }
},
Run Code Online (Sandbox Code Playgroud)
  1. 添加您的定制扩展圣所服务提供商
php artisan make:provider ExtendedSanctumServiceProvider
Run Code Online (Sandbox Code Playgroud)
  1. 扩展基础 SanctumServiceProvider 并覆盖 createGuard 方法,添加您的自定义 Guard。这看起来像下一个例子

<?php

namespace App\Providers;

use App\Guards\SanctumGuard;
use Illuminate\Auth\RequestGuard;
use Illuminate\Support\Facades\Log;
use Laravel\Sanctum\SanctumServiceProvider;

class ExtendedSanctumServiceProvider extends SanctumServiceProvider
{
    /**
     * Register the guard.
     *
     * @param  \Illuminate\Contracts\Auth\Factory  $auth
     * @param  array  $config
     * @return RequestGuard
     */
    protected function createGuard($auth, $config)
    {
        return new RequestGuard(
            new SanctumGuard($auth, config('sanctum.expiration'), $config['provider']),
            request(),
            $auth->createUserProvider($config['provider'] ?? null)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 创建您在下面定义的自定义 Sanctum Guard,扩展基本 Sanctum Guard 并覆盖 isValidAccessToken 方法
<?php

namespace App\Guards;

use Laravel\Sanctum\Guard as BaseSanctumGuard;
use Laravel\Sanctum\Sanctum;

class SanctumGuard extends BaseSanctumGuard
{
    /**
     * Determine if the provided access token is valid.
     *
     * @param  mixed  $accessToken
     * @return bool
     */
    protected function isValidAccessToken($accessToken): bool
    {
        if (! $accessToken) {
            return false;
        }

        $last_used_at = $accessToken->last_used_at;
        if(!$last_used_at) $last_used_at = $accessToken->created_at;

        $isValid =
            (! $this->expiration || $last_used_at->gt(now()->subMinutes($this->expiration)))
            && $this->hasValidProvider($accessToken->tokenable);

        if (is_callable(Sanctum::$accessTokenAuthenticationCallback)) {
            $isValid = (bool) (Sanctum::$accessTokenAuthenticationCallback)($accessToken, $isValid);
        }

        return $isValid;
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在 app.php > 'providers' 中注册您的服务提供商
/*
* Application Service Providers...
*/
...
App\Providers\AppServiceProvider::class,
App\Providers\ExtendedSanctumServiceProvider::class,
.
.
.
Run Code Online (Sandbox Code Playgroud)

有了这一切,你就可以出发了


归档时间:

查看次数:

3876 次

最近记录:

3 年,2 月 前