Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Passport Cache Client Laravel Package

overtrue/laravel-passport-cache-client

Caches Laravel Passport access tokens, clients, and scopes in Redis or any cache store, eliminating repeated database queries during authentication. Drop-in service provider with configurable TTL and cache driver, working alongside existing Passport setups.

View on GitHub
Deep Wiki
Context7

Getting Started

overtrue/laravel-passport-cache-client is a small decorator around Laravel Passport's ClientRepository that caches oauth_clients lookups, so token issuance (POST /oauth/token), personal access token creation, and Client::find() calls stop hitting the oauth_clients table on every request.

2.1.1 is a patch release — the only artifact published is a compare link against 2.1.0 with no feature, fix, or breaking-change notes. Treat it as a drop-in replacement: bump the constraint, run the suite, ship. Nothing in the release warrants new configuration or migration work.

Minimal steps:

  1. Confirm Passport is already installed and working (php artisan passport:install, keys generated, oauth_clients populated). This package replaces a binding Passport owns — installing it before Passport is configured just gives you an empty cache of nothing.
  2. composer require overtrue/laravel-passport-cache-client — the service provider is auto-discovered, there is no manual config/app.php entry.
  3. Publish the config so the TTL and cache store are explicit rather than whatever the defaults happen to be: php artisan vendor:publish --provider="Overtrue\LaravelPassportCacheClient\PassportCacheClientServiceProvider"
  4. Verify the swap actually happened before trusting it:
    // php artisan tinker
    get_class(app(Laravel\Passport\ClientRepository::class));
    // should NOT be Laravel\Passport\ClientRepository
    

First use case: a token endpoint under load. Open Telescope (or DB::listen) on a staging box, hit /oauth/token twice, and watch for the select * from oauth_clients where id = ? query disappearing on the second call. That single query is the entire value proposition; if it's still there, the binding was overridden or the cache is misconfigured and you should stop before tuning TTLs.

Where to look first: the published config file (store, TTL, key prefix), then PassportCacheClientServiceProvider to see exactly which bindings it touches in your installed version — the README tracks 2.x loosely and the provider is the source of truth.

Implementation Patterns

Zero-config drop-in for the common case. Most apps should install it, point it at a shared cache store (Redis/Memcached, not file or array), set a TTL you can defend, and change nothing else. Passport's own code paths — password grant, client credentials, personal access tokens, passport:client — all go through the repository, so they all benefit without edits.

Production config shape. The two knobs that matter:

  • Store: must be shared across every web/queue node. file cache on three load-balanced servers means three divergent views of your clients; a secret rotated on one node is still live on the others until TTL expiry.
  • TTL: a trade-off between DB load and revocation lag. A stolen client secret remains usable until the cached entry expires, so long TTLs (hours) are only acceptable if you can clear the cache on revocation. Fifteen to sixty minutes is a defensible starting point; measure first.

Deploy-hook invalidation. The single most useful integration pattern: whenever a deploy includes anything that writes to oauth_clients — a seeder, a migration that alters client flags, a credential rotation script — clear the client cache as part of the release. Wire it into your deploy script next to config:cache and queue:restart. This lets you keep a longer TTL without a correctness risk.

Write through Eloquent, not SQL. Updates that go through the client model let the package's model events invalidate the relevant entry. Raw DB::table('oauth_clients')->update(...) in an admin panel, seeder, or another service bypasses that entirely and leaves a stale entry sitting there. If you have a custom client-management UI, either use the model or explicitly forget the entry after writing.

Multiple clients / multi-tenant. Each client is cached under its own key, so many clients is fine — but the cache prefix must be environment-scoped. Staging and production sharing a Redis instance with the same prefix will happily serve each other's client records, and the failure mode (wrong redirect URI, wrong grant type) is confusing rather than loud.

Test suite isolation. Tests that create a client via factory, hit the token endpoint, then delete/refresh the DB will inherit cached entries keyed to recycled IDs on SQLite. Either set the package's cache store to array in phpunit.xml / phpunit.xml.dist (fast, no cross-test leakage) or flush the client cache in setUp. Don't let CI silently test against a warm cache from a previous test.

Long-lived workers (Octane, Horizon, queue). Because caching lives in Laravel's cache rather than process memory, workers mostly behave. The exception is the array store, which under Octane persists per-worker across requests — safe for tests, wrong for a daemon.

Extend rather than fork. If you need custom key naming, tagging, or a warm-up command, subclass the package's cache repository and rebind Laravel\Passport\ClientRepository in your own provider registered after Passport's. Keep the override in one place; scattering rebinds across providers is how you end up debugging which repository won.

Gotchas and Tips

  • Revocation lag is the whole risk. Deleting a client or rotating a secret does not necessarily propagate immediately. If your security model assumes instant revocation, either keep the TTL short or make "clear client cache" part of the revocation procedure. This is the pitfall that bites people in production, not performance.
  • personal_access_client / password_client flags are cached too. The repository caches the flag-based lookups, not just find($id). Flipping a client from password grant to client-credentials in the DB without clearing the cache means Passport keeps validating against the old shape. Symptom: unsupported_grant_type or invalid_client for a client you "already fixed."
  • Empty cache after a Redis eviction or flush is not an outage — it degrades to Passport's normal behavior. Worth knowing so you don't panic-page when cache:clear runs. Conversely, a stale cache is worse than no cache; when in doubt, flush.
  • Binding order matters. If you register a custom ClientRepository binding (common with custom client models or a tenancy setup), check which one wins: app(ClientRepository::class) in tinker is the only reliable answer. Silent last-write-wins is the usual cause of "the package isn't doing anything."
  • Passport::useClientModel() interacts with this. A custom client model plus a cached repository is fine, but confirm the cached records are hydrated as your model — otherwise you get base Client instances without your accessors/scopes and subtle null-related bugs downstream.
  • Debugging checklist, in order: (1) get_class(app(ClientRepository::class)); (2) config's store/TTL actually loaded (config('...') — remember config:cache in production freezes it); (3) DB::listen or Telescope on two consecutive token requests; (4) inspect the cache keys directly in Redis (SCAN on your prefix). Ninety percent of "it isn't caching" reports are a config cache that predates the install.
  • Don't stack caching layers blindly. If you've already added a response cache or an HTTP-layer cache in front of /oauth/token, this package's win shrinks and its invalidation surface grows. Measure the query first.
  • Upgrade discipline for 2.x patches. Release notes in this project are often just a compare link (2.1.1 is exactly that), so pin to ^2.1 and read the diff between tags before bumping minor versions — the changelog alone won't tell you whether a binding or config key moved.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log