├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .php-cs-fixer.php ├── README.md ├── composer.json └── src ├── CacheTokenRepository.php └── CacheTokenServiceProvider.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = false 10 | 11 | [*.{vue,js,scss}] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | end_of_line = lf 16 | insert_final_newline = true 17 | trim_trailing_whitespace = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [overtrue] 2 | patreon: overtrue 3 | custom: https://www.easywechat.com/img/pay/wechat.jpg 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | php_cs_fixer: 6 | name: PHP-CS-Fxier 7 | runs-on: ubuntu-latest 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | php_version: 12 | - 8.0 13 | - 8.1 14 | perfer: 15 | - stable 16 | steps: 17 | - uses: actions/checkout@master 18 | - name: Install Dependencies 19 | run: composer install --prefer-dist --no-interaction --no-suggest 20 | 21 | phpunit: 22 | name: phpunit 23 | runs-on: ubuntu-latest 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | php_version: 28 | - 8.0 29 | - 8.1 30 | perfer: 31 | - stable 32 | steps: 33 | - uses: actions/checkout@master 34 | - name: Install Dependencies 35 | run: composer install --prefer-dist --no-interaction --no-suggest 36 | - name: Run PHPUnit 37 | run: ./vendor/bin/phpunit 38 | -------------------------------------------------------------------------------- /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | setRules([ 5 | '@PSR12' => true, 6 | 'binary_operator_spaces' => true, 7 | 'blank_line_after_opening_tag' => true, 8 | 'compact_nullable_typehint' => true, 9 | 'declare_equal_normalize' => true, 10 | 'lowercase_cast' => true, 11 | 'lowercase_static_reference' => true, 12 | 'new_with_braces' => true, 13 | 'no_blank_lines_after_class_opening' => true, 14 | 'no_leading_import_slash' => true, 15 | 'no_whitespace_in_blank_line' => true, 16 | 'no_unused_imports' => true, 17 | 'ordered_class_elements' => [ 18 | 'order' => [ 19 | 'use_trait', 20 | ], 21 | ], 22 | 'ordered_imports' => [ 23 | 'imports_order' => [ 24 | 'class', 25 | 'function', 26 | 'const', 27 | ], 28 | 'sort_algorithm' => 'none', 29 | ], 30 | 'return_type_declaration' => true, 31 | 'short_scalar_cast' => true, 32 | 'single_blank_line_before_namespace' => true, 33 | 'single_trait_insert_per_statement' => true, 34 | 'ternary_operator_spaces' => true, 35 | 'unary_operator_spaces' => true, 36 | 'visibility_required' => [ 37 | 'elements' => [ 38 | 'const', 39 | 'method', 40 | 'property', 41 | ], 42 | ], 43 | ]) 44 | ->setFinder( 45 | PhpCsFixer\Finder::create() 46 | ->exclude('vendor') 47 | ->in([__DIR__.'/src/', __DIR__.'/tests/']) 48 | ) 49 | ; 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | > 🚨 This package was created because of this issue: laravel/passport#382 . But the new version of passport has officially solved this issue at: laravel/passport#1447, so I think we can stop needing this package. 3 | 4 | 5 | # Laravel Passport Cache Token 6 | 7 | Make [laravel/passport](https://github.com/laravel/passport) token cacheable. 8 | 9 | [![Sponsor me](https://github.com/overtrue/overtrue/blob/master/sponsor-me-button-s.svg?raw=true)](https://github.com/sponsors/overtrue) 10 | 11 | 12 | ## Installing 13 | 14 | ```shell 15 | $ composer require overtrue/laravel-passport-cache-token -vvv 16 | ``` 17 | 18 | ## Usage 19 | 20 | Thanks to Laravel's automatic package discovery mechanism, you don't need to do any additional operations. 21 | 22 | Of course, you can also control the cache strategy freely, just need to configure the following in the configuration file: 23 | 24 | **config/passport.php** 25 | ```php 26 | return [ 27 | //... 28 | 'cache' => [ 29 | // Cache key prefix 30 | 'prefix' => 'passport_', 31 | 32 | // The lifetime of token cache, 33 | // Unit: second 34 | 'expires_in' => 300, 35 | 36 | // Cache tags 37 | 'tags' => [], 38 | ], 39 | ]; 40 | ``` 41 | 42 | 43 | ## :heart: Sponsor me 44 | 45 | [![Sponsor me](https://github.com/overtrue/overtrue/blob/master/sponsor-me.svg?raw=true)](https://github.com/sponsors/overtrue) 46 | 47 | 如果你喜欢我的项目并想支持它,[点击这里 :heart:](https://github.com/sponsors/overtrue) 48 | 49 | 50 | ## Project supported by JetBrains 51 | 52 | Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects. 53 | 54 | [![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/overtrue) 55 | 56 | ## Contributing 57 | 58 | You can contribute in one of three ways: 59 | 60 | 1. File bug reports using the [issue tracker](https://github.com/overtrue/laravel-passport-cache-token/issues). 61 | 2. Answer questions or fix bugs on the [issue tracker](https://github.com/overtrue/laravel-passport-cache-token/issues). 62 | 3. Contribute new features or update the wiki. 63 | 64 | _The code contribution process is not very formal. You just need to make sure that you follow the PSR-0, PSR-1, and PSR-2 coding guidelines. Any new code contributions must be accompanied by unit tests where applicable._ 65 | 66 | ## License 67 | 68 | MIT 69 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "overtrue/laravel-passport-cache-token", 3 | "description": "Make laravel/passport token cacheable.", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "overtrue", 8 | "email": "anzhengchao@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "illuminate/cache": "^8.0|^9.0|^10.0", 13 | "illuminate/contracts": "^8.0|^9.0|^10.0", 14 | "illuminate/database": "^8.0|^9.0|^10.0", 15 | "illuminate/support": "^8.0|^9.0|^10.0", 16 | "illuminate/auth": "^8.0|^9.0|^10.0", 17 | "laravel/passport": "^10.0|^11.0" 18 | }, 19 | "require-dev": { 20 | "friendsofphp/php-cs-fixer": "^3.0", 21 | "orchestra/testbench": "^7.0", 22 | "mockery/mockery": "^1.4", 23 | "phpunit/phpunit": "^9.5", 24 | "brainmaestro/composer-git-hooks": "dev-master" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "Overtrue\\LaravelPassportCacheToken\\": "./src" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Tests\\": "./tests" 34 | } 35 | }, 36 | "extra": { 37 | "hooks": { 38 | "pre-commit": [ 39 | "composer test", 40 | "composer check-style" 41 | ], 42 | "pre-push": [ 43 | "composer test", 44 | "composer check-style" 45 | ] 46 | }, 47 | "laravel": { 48 | "providers": [ 49 | "Overtrue\\LaravelPassportCacheToken\\CacheTokenServiceProvider" 50 | ] 51 | } 52 | }, 53 | "scripts": { 54 | "post-update-cmd": [ 55 | "cghooks update" 56 | ], 57 | "post-merge": "composer install", 58 | "post-install-cmd": [ 59 | "cghooks add --ignore-lock", 60 | "cghooks update" 61 | ], 62 | "cghooks": "vendor/bin/cghooks", 63 | "check-style": "php-cs-fixer fix --using-cache=no --diff --dry-run --ansi", 64 | "fix-style": "php-cs-fixer fix --using-cache=no --ansi", 65 | "test": "vendor/bin/phpunit" 66 | }, 67 | "scripts-descriptions": { 68 | "test": "Run all tests.", 69 | "check-style": "Run style checks (only dry run - no fixing!).", 70 | "fix-style": "Run style checks and fix violations." 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/CacheTokenRepository.php: -------------------------------------------------------------------------------- 1 | cacheKeyPrefix = sprintf('%s_token_', $cacheKeyPrefix ?? 'passport'); 44 | $this->expiresInSeconds = $expiresInSeconds ?? 5 * 60; 45 | $this->cacheTags = $tags; 46 | $this->cacheStore = $store ?? \config('cache.default'); 47 | } 48 | 49 | /** 50 | * Get a token by the given ID. 51 | * 52 | * @param string $id 53 | * 54 | * @return \Laravel\Passport\Token 55 | */ 56 | public function find($id): ?Token 57 | { 58 | return $this->cacheStore()->remember( 59 | $this->itemKey($id), 60 | \now()->addSeconds($this->expiresInSeconds), 61 | function () use ($id) { 62 | return Passport::token()->where('id', $id)->first(); 63 | } 64 | ); 65 | } 66 | 67 | /** 68 | * Get a token by the given user ID and token ID. 69 | * 70 | * @param string $id 71 | * @param int $userId 72 | * 73 | * @return \Laravel\Passport\Token|null 74 | */ 75 | public function findForUser($id, $userId): ?Token 76 | { 77 | return $this->cacheStore()->remember( 78 | $this->itemKey($id), 79 | \now()->addSeconds($this->expiresInSeconds), 80 | function () use ($id, $userId) { 81 | return Passport::token()->where('id', $id)->where('user_id', $userId)->first(); 82 | } 83 | ); 84 | } 85 | 86 | /** 87 | * Get the token instances for the given user ID. 88 | * 89 | * @param mixed $userId 90 | * 91 | * @return \Illuminate\Database\Eloquent\Collection 92 | */ 93 | public function forUser($userId): Collection 94 | { 95 | return $this->cacheStore()->remember( 96 | $this->itemKey($userId), 97 | \now()->addSeconds($this->expiresInSeconds), 98 | function () use ($userId) { 99 | return Passport::token()->where('user_id', $userId)->get(); 100 | } 101 | ); 102 | } 103 | 104 | /** 105 | * Get a valid token instance for the given user and client. 106 | * 107 | * @param \Illuminate\Database\Eloquent\Model $user 108 | * @param \Laravel\Passport\Client $client 109 | * 110 | * @return \Laravel\Passport\Token|null 111 | */ 112 | public function getValidToken($user, $client): ?Token 113 | { 114 | return $this->cacheStore()->remember( 115 | $this->itemKey($user->getKey()), 116 | \now()->addSeconds($this->expiresInSeconds), 117 | function () use ($client, $user) { 118 | return $client->tokens() 119 | ->whereUserId($user->getKey()) 120 | ->where('revoked', 0) 121 | ->where('expires_at', '>', \now()) 122 | ->first(); 123 | } 124 | ); 125 | } 126 | 127 | public function itemKey(string $key): string 128 | { 129 | return $this->cacheKeyPrefix . $key; 130 | } 131 | 132 | public function cacheStore(): Repository 133 | { 134 | $store = Cache::store($this->cacheStore); 135 | 136 | return $store->getStore() instanceof TaggableStore ? $store->tags($this->cacheTags) : $store; 137 | } 138 | 139 | public function revokeAccessToken($id) 140 | { 141 | parent::revokeAccessToken($id); 142 | 143 | $this->cacheStore()->forget($this->itemKey($id)); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/CacheTokenServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(TokenRepository::class, function () { 13 | return new CacheTokenRepository( 14 | \config('passport.cache.prefix'), 15 | \config('passport.cache.expires_in'), 16 | \config('passport.cache.tags', []), 17 | \config('passport.cache.store', \config('cache.default')) 18 | ); 19 | }); 20 | } 21 | } 22 | --------------------------------------------------------------------------------