8ff67d19fb
Three-layer fix for the "session keeps dying with invalid_grant" pain:
1. Authentik provider config (separate change via API):
access_token_validity bumped 5min → 60min so refreshes are 12x less
frequent. Refresh-token rotation collisions only happen during the
refresh, so a longer access_token TTL means far fewer windows.
2. jwt callback (auth-options.ts): when Authentik responds 400
invalid_grant on refresh, the stored refresh_token is permanently
dead — Authentik rotated it on a previous successful refresh and the
old value can't be reused. Clear it (and the access_token) from the
JWT so subsequent session checks see a clean RefreshAccessTokenError
instead of looping into the same 400 every 5 minutes.
3. SessionErrorWatcher (new client component, mounted in providers
tree): listens for session.error === "RefreshAccessTokenError" and
calls signIn("authentik") with the current URL as callback. The
cleared JWT cookie means Authentik runs a full OIDC flow, mints fresh
tokens, and the user lands back where they were. No manual logout.
Net effect: refresh storms become invisible — at worst there's a single
redirect to Authentik (silent if the user is still SSO'd) instead of a
broken session that 401s every API call.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.0 KiB
TypeScript
36 lines
1.0 KiB
TypeScript
'use client';
|
|
|
|
import { ThemeProvider } from '@/core/theme';
|
|
import { I18nProvider } from '@/core/i18n';
|
|
import { StorageProvider } from '@/core/storage';
|
|
import { FeatureFlagProvider } from '@/core/feature-flags';
|
|
import { AuthProvider } from '@/core/auth';
|
|
import { VersionWatcher } from '@/core/version/version-watcher';
|
|
import { SessionErrorWatcher } from '@/core/auth/session-error-watcher';
|
|
import { DEFAULT_FLAGS } from '@/config/flags';
|
|
|
|
// Ensure module registry is populated
|
|
import '@/config/modules';
|
|
|
|
interface ProvidersProps {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function Providers({ children }: ProvidersProps) {
|
|
return (
|
|
<ThemeProvider>
|
|
<I18nProvider>
|
|
<StorageProvider>
|
|
<FeatureFlagProvider flagDefinitions={DEFAULT_FLAGS}>
|
|
<AuthProvider>
|
|
{children}
|
|
<VersionWatcher />
|
|
<SessionErrorWatcher />
|
|
</AuthProvider>
|
|
</FeatureFlagProvider>
|
|
</StorageProvider>
|
|
</I18nProvider>
|
|
</ThemeProvider>
|
|
);
|
|
}
|