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 Jwt Redis Laravel Package

chantouch/laravel-jwt-redis

View on GitHub
Deep Wiki
Context7

Getting Started

chantouchsek/laravel-jwtredis layers Redis-backed token state on top of JWT auth: tokens are still signed JWTs, but issuance, refresh and revocation are tracked in Redis so a token can be killed before its exp claim. Treat it as "JWT for transport, Redis for lifecycle".

  1. composer require chantouchsek/laravel-jwtredis — the service provider and middleware aliases are auto-discovered; there is nothing to register in config/app.php.
  2. Publish the config (php artisan vendor:publish --provider="Chantouchsek\\JwtRedis\\...Provider" — check --tag output, there is usually a config tag) and read the whole file before touching anything else. It is short and every key maps to a runtime behaviour.
  3. Set the environment: JWT_SECRET (generate it, never commit it), the Redis connection/database used for token storage, and the TTL / refresh-TTL pair. Point token storage at a separate Redis database or key prefix from your cache and sessions.
  4. First use case: a login endpoint that returns a token, and a protected route group:
Route::post('/login', [AuthController::class, 'login']);

Route::middleware(['auth:api'])->group(function () {
    Route::get('/me', fn (Request $r) => $r->user());
    Route::post('/refresh', [AuthController::class, 'refresh']); // refreshable middleware
});

Where to look first: config/ after publishing, then src/Http/Middleware — the refreshable middleware is the integration point most applications end up subclassing or wrapping. The README's middleware alias table is the fastest map of what you actually get.

Implementation Patterns

Login / issuance. Keep the controller thin: authenticate credentials, then let the guard issue the token. Whatever the package returns (token, access_token, expires_in, token_type), normalise it to one response shape in a small AuthResponse resource so mobile and web clients do not diverge. Store the jti you get back — you will want it for logs and for targeted revocation.

Route protection. Apply the package's auth middleware to route groups rather than sprinkling it on controllers. Keep Laravel's auth middleware order explicit: token parsing must happen before anything that reads $request->user(). If you use route-model binding with authorisation, the auth middleware has to sit ahead of can: / authorize() calls in the stack.

Refresh flow. The refreshable middleware is the piece changed in v3.2.1, and it is the piece you will interact with daily. Two patterns work:

  • Middleware-driven: attach the refreshable middleware to the endpoints that should roll the token, and read the new token off the response header (Authorization) on the client. Simplest, but every consumer must handle a changed header.
  • Explicit endpoint: a /refresh route that invalidates the presented token in Redis and returns a fresh pair. Easier to test and to document; prefer this when you have third-party clients.

Whichever you pick, rotate: invalidate the old jti on refresh so a leaked refresh token is single-use.

Revocation and multi-device sessions. This is the reason to pick this package. Key Redis entries by sub + jti (or a per-user set of jtis) so you can implement "log out this device" (delete one key) and "log out everywhere" (delete the user's set) as one-liners in a service class. Wire logout to the same service rather than calling the guard directly from the controller, or the two paths will drift.

Testing. Do not assume the array cache driver covers you — token state lives in Redis. Give the test suite its own Redis database, flush it in setUp, and write one test that asserts a token stops working immediately after revocation. That test is the whole value proposition of the package and it should be the first thing that breaks if configuration regresses.

Non-HTTP contexts. Queues and artisan commands do not run middleware, so a token in a job payload must be validated by resolving the guard manually. If background work only needs the user identity, pass the user id and re-fetch rather than ferrying tokens around.

Gotchas and Tips

The v3.2.1 fix touches you if you subclass. The release corrects the return types declared on the refreshable middleware. That is behaviourally inert — no request/response handling changed — but PHP is strict about signature compatibility in subclasses and decorators. If you extended the middleware (or wrapped it and re-declared handle(...): Response), run your test suite after composer update: a parent whose return type widens to mixed will reject a child that narrowed it. Covariance the other way is fine. Otherwise, upgrading from 3.2.0 is a drop-in patch and safe to take.

TTL must agree in both places. A JWT is valid until exp; a Redis entry is valid until its TTL. If the Redis TTL is shorter than the JWT lifetime you get tokens that pass signature verification but fail the storage lookup — intermittent "randomly logged out" bugs that only appear after the refresh window. Make the Redis TTL the source of truth and set the JWT exp from it, not the reverse.

Fail-open vs fail-closed when Redis is down. Decide deliberately and encode it in config, because the default matters during an outage: fail-closed logs every user out, fail-open silently disables revocation. For most apps the right answer is fail-closed on protected writes and a loud alert on the Redis connection; whatever you choose, document it, because it is an incident-time decision you do not want to make at 3am.

Namespace your Redis keys. Sharing database 0 with cache, sessions and Horizon is the most common setup mistake. A prefix plus a dedicated database number costs nothing and makes redis-cli --scan --pattern 'jwt:*' a usable debugging tool instead of a hazard.

Concurrent refresh is a race. Two parallel requests from the same client both hitting the refresh path will have one rotation invalidate the other's token. Either add a short Redis lock keyed on the old jti, or let clients tolerate a refresh failure by retrying once with the newly issued token. Mobile clients on flaky networks hit this constantly.

Expose the header through CORS. If the refresh middleware returns the new token in Authorization, add it to exposed_headers in config/cors.php or browser clients will never see it and will keep replaying the dead token.

Clock skew. Servers with drifting clocks reject freshly minted tokens. A small leeway (30–60s) in the JWT config removes a class of "token invalid immediately after login" reports that are otherwise very hard to reproduce.

Debugging. Log the jti and sub at issuance and at every rejection — without it, a Redis lookup miss and a signature failure look identical in the logs. redis-cli MONITOR against a staging instance shows you exactly which keys the package reads and writes, which is the fastest way to confirm the prefix and TTL settings are what you think they are.

Extension points. The token storage/payload handling is the seam worth knowing: bind your own implementation in a service provider if you need to change key naming, add per-tenant isolation, or publish revocation events to a message bus. Prefer that over forking the middleware — forks are what make the v3.2.1-style signature fix painful.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource