AuthProvider component creates a React context that manages authentication state, handles automatic token refresh, and provides auth methods to all child components via hooks.
interface AuthProviderProps {
children: ReactNode;
config: AuthSafeConfig;
initialSession?: AuthSession | null;
}interface AuthSafeConfig {
clientId: string; // OAuth client ID
domain: string; // AuthSafe domain
redirectUri?: string; // Default: /api/auth/callback
scopes?: string[]; // Default: ['openid', 'email', 'profile']
cookies?: {
prefix?: string; // Default: 'authsafe'
domain?: string;
path?: string; // Default: '/'
secure?: boolean; // Default: true in production
sameSite?: 'strict' | 'lax' | 'none'; // Default: 'lax'
};
session?: {
maxAge?: number; // Session duration in seconds (default: 3600)
autoRefresh?: boolean; // Default: true
};
}interface AuthSession {
userId: string;
email: string;
name?: string;
emailVerified: boolean;
organizationId: string;
issuedAt: number;
expiresAt: number;
}// app/layout.tsx
import { AuthProvider } from 'authsafe-nextjs/client';
import { getAuth, initAuthSafe } from 'authsafe-nextjs/server';
// Initialize on server-side
initAuthSafe({
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
clientSecret: process.env.AUTHSAFE_CLIENT_SECRET,
});
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
// Get session server-side
const session = await getAuth();
return (
<html lang="en">
<body>
<AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
}}
initialSession={session}
>
{children}
</AuthProvider>
</body>
</html>
);
}// pages/_app.tsx
import { AuthProvider } from 'authsafe-nextjs/client';
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return (
<AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
}}
initialSession={pageProps.session}
>
<Component {...pageProps} />
</AuthProvider>
);
}// Automatic refresh happens in the background
<AuthProvider config={config} initialSession={session}>
{/* Your app - tokens stay fresh automatically */}
</AuthProvider>// Server-rendered session is passed to client
const session = await getAuth(); // Server
<AuthProvider initialSession={session}> {/* Client hydrates with same state */}<AuthProvider config={config}>
<Header /> {/* Can use useAuth() */}
<Dashboard /> {/* Can use useSession() */}
<MfaSettings /> {/* Can use useMfa() */}
</AuthProvider><AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
cookies: {
prefix: 'myapp', // Custom prefix
domain: '.example.com', // Share across subdomains
secure: true, // HTTPS only
sameSite: 'strict', // CSRF protection
},
}}
>
{children}
</AuthProvider><AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
session: {
maxAge: 7200, // 2 hours
autoRefresh: true, // Enable auto-refresh
},
}}
>
{children}
</AuthProvider><AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
scopes: ['openid', 'email', 'profile', 'offline_access', 'admin'],
}}
>
{children}
</AuthProvider>useAuthContext():
interface AuthContextValue {
isAuthenticated: boolean;
isLoading: boolean;
user: AuthSession | null;
error: Error | null;
signIn: (returnTo?: string) => Promise<void>;
signOut: (returnTo?: string) => Promise<void>;
refreshSession: () => Promise<void>;
config: AuthSafeConfig;
}useAuth() hook instead of useAuthContext() directly for better ergonomics.
initialSession to avoid authentication flicker during hydrationinitAuthSafe() in your root layoutautoRefresh for seamless UXmaxAge based on your security requirementsinitialSession:
// ✅ Correct
const session = await getAuth();
<AuthProvider initialSession={session}>
// ❌ Wrong - will cause hydration mismatch
<AuthProvider>// ✅ Correct
<AuthProvider config={config}>
<Component /> {/* Can use useAuth() */}
</AuthProvider>
// ❌ Wrong
<Component /> {/* No AuthProvider above */}