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

rcerljenko/laravel-jwt

A lightweight JWT authentication package for Laravel. It provides a guard, middleware, and token helpers for issuing, validating, and refreshing JSON Web Tokens, making it easy to secure APIs with stateless authentication. Simple setup and Laravel-friendly configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

rcerljenko/laravel-jwt is a thin JWT auth layer for Laravel APIs — a guard, a middleware, and a trait you put on your User model. It is not a full auth scaffold, so budget an afternoon to wire it into an existing app.

Minimal path:

  1. composer require rcerljenko/laravel-jwt (2.1.0 is additive over 2.0.x — no breaking changes, safe bump).
  2. Publish the config: php artisan vendor:publish --tag=laravel-jwt-config and check config/jwt.php first — this file is where token TTL, the signing algorithm, and (new in 2.1.0) the cookie transport settings live.
  3. Set a strong JWT_SECRET in .env. Generate one rather than typing it; rotating this later invalidates every issued token.
  4. Register the guard in config/auth.php under guards, pointing driver at the package's guard and provider at your users provider.
  5. Protect a route group with the package middleware, then hit it with a token to confirm the wiring.

Your first use case should be a single POST /api/login that validates credentials and returns a token — everything else (refresh, logout, revocation) is a variation on that. If you are building a browser SPA rather than a mobile/CLI client, jump straight to the 2.1.0 cookie mode described below, because retrofitting it later means touching every client.

Implementation Patterns

Stateless bearer flow (the default). Login controller returns ['token' => $token]; clients send Authorization: Bearer <token>. Keep token issuance in one place — a small JwtService or an action class — so TTL and claims stay consistent across login, refresh, and impersonation paths.

Cookie transport (new in 2.1.0). The package can now read the token from a cookie instead of the Authorization header. This is the right call for server-rendered apps and first-party SPAs, since an HttpOnly cookie is not reachable from JavaScript. Pattern:

  • On login, issue the token and attach it as a cookie in the response (HttpOnly, Secure, SameSite=Lax or Strict).
  • Leave the guard and middleware configuration alone — the guard simply finds the token in the cookie when the header is absent.
  • Make sure your CORS config has supports_credentials => true and an explicit origin (never *), and that the frontend sends withCredentials: true (Axios) or credentials: 'include' (fetch).
  • Add CSRF protection for cookie-authenticated state-changing routes. Bearer tokens are immune to CSRF; cookies are not. This is the single biggest thing people miss when switching transports.
  • Use a distinct cookie name per environment so a dev token on localhost:3000 doesn't shadow a staging token.

Dual transport. Because the header takes priority and the cookie is a fallback (verify this against the guard's resolution order in your version), you can serve a mobile app and a web app from the same endpoints. Be deliberate: if you accept both, document which one wins, and consider rejecting ambiguous requests in a small middleware of your own.

Revocation and logout. Short TTL plus a refresh endpoint is cheaper than a blacklist. If you need immediate logout, use the package's blacklist/invalidate support and confirm your cache driver is not array in production — an ephemeral store silently makes revocation a no-op.

Testing. In feature tests, $this->actingAs($user, 'api') usually bypasses the token entirely; write at least one test that goes through the real login endpoint and one that asserts a request with a tampered or expired token gets a 401. For cookie mode, assert on Set-Cookie via $response->assertCookie() and drive follow-up requests with withCookie().

Gotchas and Tips

  • Clock skew is the classic false negative. A token that "just expired" on a container with drifted time looks like a signing bug. Allow a small leeway in the config before you start debugging the secret.
  • JWT_SECRET rotation logs everyone out. That is correct behaviour, but plan it — deploy the new secret, keep the old one accepted during a grace window if the package allows multiple keys, or accept a hard logout.
  • Claims are signed, not encrypted. Anyone holding the token can base64-decode the payload. Never put roles you don't re-check server-side, emails, or internal IDs you consider sensitive into custom claims.
  • Guard ordering in config/auth.php bites when you add JWT alongside session auth. Laravel uses the first guard that returns a user; if web is first and a session cookie exists, your API route may authenticate via session and never touch the JWT.
  • Cookie mode debugging order: (1) is Set-Cookie actually in the response? (2) does the browser store it — check Domain, Secure on http://localhost, and SameSite? (3) is the browser sending it — check CORS credentials and withCredentials? Roughly 90% of "cookie auth doesn't work" reports die at step 2.
  • Do not put the token in localStorage and also in a cookie. Pick one. Duplicated transport is how you get a token that survives logout in one place and not the other.
  • Extension points: custom claims via the token factory/generator binding, a custom guard subclass if you need a different resolution order, and the middleware for per-route overrides. Prefer decorating the package's service over forking it — 2.1.0 is a small release and the package is actively accepting PRs, so upstream changes are likely.
  • Pin the minor version (^2.1) in composer.json and skim the diff on each bump; the changelog is terse, as 2.1.0's one-line note shows.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin