authsafe-nextjs
v0.0.5
Published
Official Next.js SDK for AuthSafe - OAuth 2.1, OIDC, and MFA for Next.js App Router and Pages Router
Maintainers
Readme
AuthSafe Next.js SDK
The official Next.js SDK for AuthSafe — secure OAuth 2.1, OIDC, and MFA integration for Next.js applications with App Router and Pages Router support.
Features
- ✅ Next.js 14+ & 15+ - Full support for App Router and Pages Router
- ✅ Server Components - Server-side authentication with RSC
- ✅ Middleware - Route protection at the edge
- ✅ Client Hooks - React hooks for authentication state
- ✅ PKCE Flow - Secure authorization code flow with PKCE
- ✅ JWT Validation - JWKS-based token verification with caching
- ✅ MFA Support - TOTP, WebAuthn, Email OTP management
- ✅ Auto Refresh - Automatic token refresh before expiration
- ✅ TypeScript First - Comprehensive type definitions
Installation
npm install authsafe-nextjsOr with other package managers:
# Yarn
yarn add authsafe-nextjs
# pnpm
pnpm add authsafe-nextjsQuick Start
1. Environment Variables
# .env.local
AUTHSAFE_CLIENT_ID=your_client_id
AUTHSAFE_CLIENT_SECRET=your_client_secret # Optional for confidential clients
AUTHSAFE_DOMAIN=https://auth.yourapp.com
# Public variables (prefixed with NEXT_PUBLIC_)
NEXT_PUBLIC_AUTHSAFE_CLIENT_ID=your_client_id
NEXT_PUBLIC_AUTHSAFE_DOMAIN=https://auth.yourapp.com2. Root Layout (App Router)
// app/layout.tsx
import { AuthProvider } from 'authsafe-nextjs/client';
import { getAuth } from 'authsafe-nextjs/server';
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await getAuth();
return (
<html>
<body>
<AuthProvider
config={{
clientId: process.env.NEXT_PUBLIC_AUTHSAFE_CLIENT_ID!,
domain: process.env.NEXT_PUBLIC_AUTHSAFE_DOMAIN!,
}}
initialSession={session}
>
{children}
</AuthProvider>
</body>
</html>
);
}3. API Routes
Create OAuth callback, sign in, and logout handlers:
// app/api/auth/callback/route.ts
import { handleCallback } from 'authsafe-nextjs/server';
export async function GET(req: NextRequest) {
return handleCallback(req, {
clientId: process.env.AUTHSAFE_CLIENT_ID!,
clientSecret: process.env.AUTHSAFE_CLIENT_SECRET,
domain: process.env.AUTHSAFE_DOMAIN!,
redirectUri: `${process.env.APP_URL}/api/auth/callback`,
});
}// app/api/auth/signin/route.ts
import { handleSignIn } from 'authsafe-nextjs/server';
export async function GET(req: NextRequest) {
return handleSignIn(req, {
clientId: process.env.AUTHSAFE_CLIENT_ID!,
domain: process.env.AUTHSAFE_DOMAIN!,
redirectUri: `${process.env.APP_URL}/api/auth/callback`,
});
}// app/api/auth/logout/route.ts
import { handleLogout } from 'authsafe-nextjs/server';
export async function POST(req: NextRequest) {
return handleLogout(req, {
clientId: process.env.AUTHSAFE_CLIENT_ID!,
domain: process.env.AUTHSAFE_DOMAIN!,
});
}4. Middleware (Optional)
Protect routes automatically:
// 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).*)'],
};Usage
Server Components
// app/dashboard/page.tsx
import { getAuth, requireAuth } from 'authsafe-nextjs/server';
// Optional auth
export default async function DashboardPage() {
const session = await getAuth();
if (!session) {
return <div>Not authenticated</div>;
}
return <div>Hello {session.email}</div>;
}
// Required auth (throws if not authenticated)
export default async function ProtectedPage() {
const session = await requireAuth();
return <div>Protected content for {session.email}</div>;
}Client Components
'use client';
import { useAuth, SignInButton, SignOutButton } from 'authsafe-nextjs/client';
export function LoginButton() {
const { isAuthenticated, user } = useAuth();
if (isAuthenticated) {
return (
<div>
<span>{user.email}</span>
<SignOutButton>Logout</SignOutButton>
</div>
);
}
return <SignInButton>Login</SignInButton>;
}MFA Management
'use client';
import { useMfa } from 'authsafe-nextjs/client';
import { useEffect } from 'react';
export function MfaSettings() {
const { methods, registerMethod, confirmMethod, fetchMethods } = useMfa();
useEffect(() => {
fetchMethods();
}, []);
const handleEnableTOTP = async () => {
const { qrcode } = await registerMethod('TOTP');
// Show QR code modal
};
return (
<div>
<h2>MFA Methods</h2>
{methods.map((method) => (
<div key={method.id}>
{method.type} - {method.isEnabled ? 'Enabled' : 'Disabled'}
</div>
))}
<button onClick={handleEnableTOTP}>Enable TOTP</button>
</div>
);
}API Reference
Server
initAuthSafe(config)- Initialize configurationgetAuth()- Get current session (returns null if not authenticated)requireAuth()- Require authentication (throws if not authenticated)currentUser()- Alias for getAuth()getAccessToken()- Get access token for API callshasScope(scope)- Check if user has specific scopehasScopes(scopes)- Check if user has all required scopes
Client
<AuthProvider>- Wrap your app with this provideruseAuth()- Main authentication hookuseSession()- Get current sessionuseMfa()- MFA management hook<SignInButton>- Pre-built sign in button<SignOutButton>- Pre-built sign out button<UserButton>- User info with dropdown
Middleware
createAuthMiddleware(config)- Create route protection middlewareauthMiddleware(config)- Simple auth status middleware
License
MIT
Support
- GitHub: authsafe/authsafe-js
- Documentation: docs.authsafe.in
Made with ❤️ by the AuthSafe team
