fix: ResolveTenant FIRST in tenant panel middleware

Filament panel routes are NOT in the 'web' middleware group; they have
their own middleware list. So registering ResolveTenant in bootstrap
app.php (web group) doesn't apply to /app/* routes.

Filament's Authenticate middleware (from authMiddleware) is inserted
between ShareErrorsFromSession and AuthenticateSession. Auth check
queries User::find($id) which goes through BelongsToTenant's TenantScope.
If tenant isn't resolved at that point, scope's fail-safe returns 0 rows
→ User not found → user appears not authenticated → infinite redirect.

Fix: put ResolveTenant + CheckTenantStatus FIRST in the panel's
middleware() chain, before any auth-related middleware runs.

Symptom that pointed here: force-login set session correctly,
auth('web')->check() returned true on a /__whoami test route, but
visiting /app redirected back to /app/login.
This commit is contained in:
2026-05-06 20:33:10 +00:00
parent dd74109adf
commit c17fb2b413
@@ -46,6 +46,14 @@ class TenantPanelProvider extends PanelProvider
\App\Filament\Tenant\Widgets\StatsOverview::class, \App\Filament\Tenant\Widgets\StatsOverview::class,
]) ])
->middleware([ ->middleware([
// CRITICAL: tenant resolution must run BEFORE Filament's
// Authenticate middleware (which is inserted by authMiddleware
// between ShareErrorsFromSession and AuthenticateSession).
// Otherwise User::find() during auth check has no tenant
// context → TenantScope returns 0 rows → user appears
// unauthenticated → endless redirect to /app/login.
ResolveTenant::class,
CheckTenantStatus::class,
EncryptCookies::class, EncryptCookies::class,
AddQueuedCookiesToResponse::class, AddQueuedCookiesToResponse::class,
StartSession::class, StartSession::class,
@@ -55,9 +63,6 @@ class TenantPanelProvider extends PanelProvider
SubstituteBindings::class, SubstituteBindings::class,
DisableBladeIconComponents::class, DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class, DispatchServingFilamentEvent::class,
// ResolveTenant + CheckTenantStatus are now registered globally
// in bootstrap/app.php (web middleware group) so they run on
// Livewire endpoints too. No need to duplicate them here.
]) ])
->authMiddleware([ ->authMiddleware([
Authenticate::class, Authenticate::class,