Minimal-dependency JWT authentication for first-party Laravel apps (Laravel 12/13) — "first-party" meaning you own both the client and the API, so there's no third party to delegate to and no OAuth ceremony to perform.
Unofficial, independent package. Not affiliated with, endorsed by, or maintained by the Laravel team. "Laravel", "Sanctum", and "Fortify" are referenced only to describe compatibility and design influence; they are trademarks of their respective owners.
- Short-lived access JWTs (HS256, 15 min) — stateless, verified on every request with the algorithm pinned and
iss/audasserted. - Opaque rotating refresh tokens (30 days) — stored only as a
sha256hash, rotated on every use. - Reuse detection — replaying a consumed token revokes the whole session (token family).
- Concurrency grace window — multiple tabs / SSR refresh without false logouts.
- Instant revocation — a cache-backed denylist kills an access token or a whole session within one request.
- Optional two-factor auth (TOTP + recovery codes) and passkeys (WebAuthn / FIDO2), each opt-in and feature-gated.
- Sanctum/Fortify-style design — a contract per swappable piece, single-purpose Actions, a static
Lukkconfig hub, a dedicated guard, and Responsable response contracts.
The single runtime dependency is firebase/php-jwt, the audited JWS primitive — never hand-roll JWT. Everything else is Laravel core.
| Access token | HS256 JWT, 15 min. Claims iss/aud/sub/fid/jti/iat/nbf/exp, header typ=at+jwt. Verified every request: alg pinned, iss/aud asserted, denylist checked by jti and fid. |
| Refresh token | Opaque 256-bit secret, 30 days. Returned once; stored only as sha256. Rotated on every refresh; reuse after the grace window revokes the whole family. |
HS256 is correct while this app is its own sole verifier. RS256/ES256 + a JWKS endpoint + kid key rotation are built in (behind the same contracts) for when an independent service must verify tokens — flip LUKK_ALGORITHM and run php artisan lukk:keygen. See Architecture & Security.
- PHP
^8.3 - Laravel
^12.0 | ^13.0 firebase/php-jwt^7.0
composer require lukk/lukk
php artisan vendor:publish --tag=lukk-config # config/lukk.php
php artisan vendor:publish --tag=lukk-migrations # refresh_tokens migration
php artisan migrate
php artisan lukk:secret # writes LUKK_SECRET to .envMap a guard to the lukk-jwt driver in config/auth.php:
'guards' => [
'api' => ['driver' => 'lukk-jwt', 'provider' => 'users'],
],Then protect routes with auth:api as usual:
Route::middleware('auth:api')->get('/me', fn (Request $r) => $r->user());The package registers login, refresh, logout, and session-revocation (DELETE /sessions, DELETE /sessions/others) routes automatically. See Installation and Authentication for the full walkthrough.
📚 Full documentation: stsepelin.github.io/lukk-docs
lukk (the Laravel package) and lukk-js (the TypeScript/Nuxt client) are documented together on one site — each feature page covers both the server and the client. Start with the Introduction or jump to Installation.
For AI assistants: the docs are exposed as /llms.txt + /llms-full.txt (llms.txt convention), and AGENTS.md has integration + contribution rules.
composer install
vendor/bin/pestMIT.