getAuth()useAuth(), useSession(), useMfa() for reactive UISignInButton, SignOutButton, UserButton, Profilenpm install authsafe-nextjs
# or
yarn add authsafe-nextjs
# or
pnpm add authsafe-nextjs.env.local file:
NEXT_PUBLIC_AUTHSAFE_CLIENT_ID=your_client_id
NEXT_PUBLIC_AUTHSAFE_DOMAIN=https://auth.yourapp.com
AUTHSAFE_CLIENT_SECRET=your_client_secret # For API routesAuthProvider:
// app/layout.tsx
import { AuthProvider } from 'authsafe-nextjs/client';
import { getAuth, initAuthSafe } from 'authsafe-nextjs/server';
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 }) {
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>
);
}// app/api/auth/signin/route.ts
import { handleSignIn } from 'authsafe-nextjs/server';
export async function GET(request: Request) {
return handleSignIn(request);
}// app/api/auth/callback/route.ts
import { handleCallback } from 'authsafe-nextjs/server';
export async function GET(request: Request) {
return handleCallback(request);
}// app/api/auth/logout/route.ts
import { handleLogout } from 'authsafe-nextjs/server';
export async function POST(request: Request) {
return handleLogout(request);
}// app/api/auth/refresh/route.ts
import { handleRefresh } from 'authsafe-nextjs/server';
export async function POST(request: Request) {
return handleRefresh(request);
}'use client';
import { useAuth, SignInButton, SignOutButton } from 'authsafe-nextjs/client';
export function Header() {
const { isAuthenticated, user } = useAuth();
if (!isAuthenticated) {
return <SignInButton className="btn-primary">Sign In</SignInButton>;
}
return (
<div>
<p>Welcome, {user?.email}</p>
<SignOutButton>Sign Out</SignOutButton>
</div>
);
}// app/dashboard/page.tsx
import { getAuth } from 'authsafe-nextjs/server';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await getAuth();
if (!session) {
redirect('/api/auth/signin');
}
return (
<div>
<h1>Dashboard</h1>
<p>Logged in as: {session.email}</p>
</div>
);
}authsafe-nextjs/client)authsafe-nextjs/server)┌─────────────────────────────────────┐
│ Client Components │
│ (useAuth, SignInButton, Profile) │
└──────────────┬──────────────────────┘
│
├──> AuthProvider (React Context)
│
├──> API Routes (/api/auth/*)
│ ├─ signin
│ ├─ callback
│ ├─ logout
│ └─ refresh
│
├──> Server Components (getAuth)
│
└──> Middleware (Route Protection)
↓
Secure HttpOnly Cookies
(id_token, access_token, refresh_token)import { requireAuth } from 'authsafe-nextjs/server';
export default async function ProtectedPage() {
const session = await requireAuth(); // Throws if not authenticated
return <div>Hello {session.email}</div>;
}'use client';
import { useAuth } from 'authsafe-nextjs/client';
export function UserProfile() {
const { isAuthenticated, user, signOut } = useAuth();
if (!isAuthenticated) return null;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
<button onClick={() => signOut()}>Sign Out</button>
</div>
);
}// middleware.ts
import { createAuthMiddleware } from 'authsafe-nextjs/server';
export default createAuthMiddleware({
authConfig: {
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
},
protectedRoutes: ['/dashboard', '/profile', /^\/admin/],
publicRoutes: ['/'],
signInUrl: '/api/auth/signin',
});
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};'use client';
import { useMfa } from 'authsafe-nextjs/client';
import { useEffect } from 'react';
export function MfaSettings() {
const { methods, fetchMethods, registerMethod } = useMfa();
useEffect(() => {
fetchMethods();
}, []);
const handleEnableTOTP = async () => {
const { qrCode } = await registerMethod('TOTP');
// Display QR code to user
};
return (
<div>
<h2>MFA Methods</h2>
{methods.map((method) => (
<div key={method.id}>{method.type}</div>
))}
<button onClick={handleEnableTOTP}>Enable TOTP</button>
</div>
);
}