-
Notifications
You must be signed in to change notification settings - Fork 11.8k
Description
Laravel Version
12.45.0
PHP Version
8.3
Database Driver & Version
No response
Description
After upgrading from Laravel v12.44.0 to v12.45.0, users experience intermittent 401 Unauthenticated errors on API routes that use Sanctum's stateful authentication. This occurs even with completely fresh logins - not just existing sessions.
The issue appears related to PR #58107 which changed the remember token to store a MAC instead of the password hash. While the stated goal was to prevent session forgery if password hashes leak, the change seems to break session validation when AuthenticateSession middleware is enabled alongside Sanctum stateful auth.
Behavior observed:
- Fresh login succeeds
- Initial page navigation works (Inertia/web routes)
- API requests intermittently return 401 Unauthenticated
- After a 401, refreshing the page logs the user out completely
- Re-logging in temporarily works, then the cycle repeats
Environment:
- Laravel v12.45.0 (works on v12.44.0)
- Sanctum with stateful authentication (SPA)
- AuthenticateSession middleware enabled in web group
- Redis session driver
- Inertia.js frontend making API calls to /api/* routes
The API routes use Sanctum's stateful middleware and share sessions with the web routes. The issue does not occur when AuthenticateSession middleware is disabled, or when staying on v12.44.0.
Steps To Reproduce
- Start with a fresh Laravel 12 app with Sanctum configured for stateful SPA auth
- Enable AuthenticateSession middleware in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [AuthenticateSession::class]);
}) - Configure Sanctum stateful domains in config/sanctum.php
- Create an API route behind auth:sanctum middleware
- Upgrade to laravel/framework v12.45.0
- Clear all sessions/cookies, open incognito browser
- Log in with valid credentials
- Navigate around - works initially
- Trigger an API call (e.g., search autocomplete, any /api/* route)
- Observe 401 Unauthenticated response
- Refresh page - user is now logged out