fauthy-next-sdk
v0.6.0
Published
Next.js auth client for Fauthy
Readme
Fauthy Next.js SDK
A Next.js authentication SDK for Fauthy. Supports magic links, passcode (OTP), password, and SSO login flows with encrypted split-cookie session storage.
Installation
npm install fauthy-next-sdkEnvironment Variables
FAUTHY_SECRET=your-secret-key # Used to encrypt session cookies
FAUTHY_API_URL=https://api.fauthy.com
FAUTHY_CLIENT_ID=your-client-id
FAUTHY_APP_ID=your-app-id
FAUTHY_CALLBACK_URL=https://your-app.com/api/auth/authorizeSetup
1. Create a shared client
// lib/fauthy.ts
import { FauthyClient } from 'fauthy-next-sdk';
export const fauthy = new FauthyClient({
secret: process.env.FAUTHY_SECRET!,
session_ttl: 86400 * 30, // 30 days (default)
noAuthRedirectUrl: '/api/auth/logout', // default
});2. Add API route handlers
Create the following routes under app/api/auth/:
// app/api/auth/login/passwordless/route.ts
import { NextRequest } from 'next/server';
import { handleLoginPasswordless } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function POST(req: NextRequest) {
return handleLoginPasswordless(req);
}// app/api/auth/authorize/route.ts (magic link callback)
import { NextRequest } from 'next/server';
import { handleAuthorize } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function GET(req: NextRequest) {
return handleAuthorize(req, fauthy, '/dashboard');
}// app/api/auth/login/passcode/route.ts
import { NextRequest } from 'next/server';
import { handleLoginPasscode } from 'fauthy-next-sdk';
export async function POST(req: NextRequest) {
return handleLoginPasscode(req);
}// app/api/auth/authorize/passcode/route.ts
import { NextRequest } from 'next/server';
import { handleAuthorizePasscode } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function POST(req: NextRequest) {
return handleAuthorizePasscode(req, fauthy);
}// app/api/auth/login/password/route.ts
import { NextRequest } from 'next/server';
import { handleLoginPassword } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function POST(req: NextRequest) {
return handleLoginPassword(req, fauthy);
}// app/api/auth/register/route.ts
import { NextRequest } from 'next/server';
import { handleRegister } from 'fauthy-next-sdk';
export async function POST(req: NextRequest) {
return handleRegister(req);
}// app/api/auth/verify-email/route.ts
import { NextRequest } from 'next/server';
import { handleVerifyEmail } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function GET(req: NextRequest) {
return handleVerifyEmail(req, fauthy, '/dashboard', '/auth/login');
}// app/api/auth/logout/route.ts
import { NextRequest } from 'next/server';
import { handleLogout } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function GET(req: NextRequest) {
return handleLogout(req, fauthy, '/', '/auth/login');
}// app/api/auth/me/route.ts
import { NextRequest } from 'next/server';
import { handleMe, handleUpdateMe } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function GET(req: NextRequest) {
return handleMe(req, fauthy);
}
export async function POST(req: NextRequest) {
return handleUpdateMe(req, fauthy);
}SSO Routes
// app/api/auth/sso/providers/route.ts
import { NextRequest } from 'next/server';
import { handleSSOProviders } from 'fauthy-next-sdk';
export async function GET(req: NextRequest) {
return handleSSOProviders(req);
}// app/api/auth/sso/start/route.ts (?provider=google)
import { NextRequest } from 'next/server';
import { handleSSOStart } from 'fauthy-next-sdk';
export async function GET(req: NextRequest) {
return handleSSOStart(req);
}// app/api/auth/sso/callback/route.ts
import { NextRequest } from 'next/server';
import { handleSSOCallback } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export async function GET(req: NextRequest) {
return handleSSOCallback(req, fauthy, '/dashboard');
}3. Provide user context (server layout)
// app/layout.tsx
import { FauthyProvider, ClaimsProvider, ensureValidSession, me, getClaimsFromSession } from 'fauthy-next-sdk';
import { fauthy } from '@/lib/fauthy';
export default async function RootLayout({ children }: { children: React.ReactNode }) {
let user = null;
let claims = {};
const session = await fauthy.getSession();
const user = session ? session.user : null;
if (session) {
try {
const validSession = await ensureValidSession(fauthy, session);
const userResponse = await me(validSession.access_token);
if (userResponse.status?.code === 200) {
user = userResponse.data;
}
claims = await getClaimsFromSession(validSession);
} catch {
// Session invalid — user will be redirected on next protected route visit
}
}
return (
<html>
<body>
<FauthyProvider user={user}>
<ClaimsProvider claims={claims}>
{children}
</ClaimsProvider>
</FauthyProvider>
</body>
</html>
);
}4. Use in client components
Import hooks and client helpers from their subpaths — do not import from the main fauthy-next-sdk barrel in client components, as it also exports server-only modules:
'use client';
import { useUser, useClaims } from 'fauthy-next-sdk/providers';
import { hasRole, hasPermission } from 'fauthy-next-sdk/utils/client';
export function UserGreeting() {
const user = useUser();
if (!user) return <p>Please log in</p>;
return <p>Welcome, {user.first_name}!</p>;
}
export function AdminPanel() {
const claims = useClaims();
if (!hasRole(claims, 'admin')) return <p>Access denied</p>;
return <div>Admin content</div>;
}Session Management
Server-side
import { getSession, ensureValidSession, callExternalAPI, handleExternalApiProxy } from 'fauthy-next-sdk/route';
import { getRequestCookieHeader } from 'fauthy-next-sdk/utils/server';
import { fauthy } from '@/lib/fauthy';
// Get session from cookies
const session = await getSession(fauthy);
// Validate session and refresh access token if expired (Route Handlers only)
const validSession = await ensureValidSession(fauthy, session);
// Make an authenticated request to an external API (Route Handlers only)
const response = await callExternalAPI(fauthy, 'https://api.example.com/data', {
method: 'GET',
});
// Forward cookies when calling an auth API route from a Server Component
const cookieHeader = await getRequestCookieHeader();For backend API calls from Server Components, use a catch-all proxy route with handleExternalApiProxy. See API Routes Setup.
Role & Permission Helpers
These helpers accept the claims object returned by getClaimsFromSession or useClaims.
import {
hasRole,
hasAnyRole,
hasAllRoles,
hasPermission,
hasAnyPermission,
hasAllPermissions,
getClaimsPermissions,
} from 'fauthy-next-sdk';
hasRole(claims, 'admin')
hasAnyRole(claims, ['admin', 'moderator'])
hasAllRoles(claims, ['admin', 'superuser'])
hasPermission(claims, 'user:read')
hasAnyPermission(claims, ['user:read', 'user:write'])
hasAllPermissions(claims, ['user:read', 'user:write'])
getClaimsPermissions(claims) // string[]Cookie Architecture
Sessions are stored across four separate encrypted cookies (JWE / A256GCM):
| Cookie | Contents |
|---|---|
| __fauthy_user | User profile (uuid, name, email) |
| __fauthy_session | Session metadata (uuid, expiry) |
| __fauthy_authtoken | Access token (JWT) |
| __fauthy_refreshtoken | Refresh token |
All cookies are httpOnly, sameSite: lax, and secure in production.
Module Exports
| Import path | Contents |
|---|---|
| fauthy-next-sdk | Everything (client, route handlers, providers, hooks, utilities, types) |
| fauthy-next-sdk/api | Low-level Fauthy API functions |
| fauthy-next-sdk/client | FauthyClient class |
| fauthy-next-sdk/route | Next.js route handler helpers |
| fauthy-next-sdk/providers | FauthyProvider, ClaimsProvider, useUser, useClaims |
| fauthy-next-sdk/cookies | Cookie encryption utilities |
| fauthy-next-sdk/utils/server | decodeJWTClaims, getClaimsFromSession |
| fauthy-next-sdk/utils/client | Role/permission helpers |
| fauthy-next-sdk/types | TypeScript types |
Types
import type { SessionData, SessionUser, User, CookieOptions } from 'fauthy-next-sdk';
// User — full profile returned by /auth/me
type User = {
uuid: string;
first_name: string;
last_name: string;
email: string;
roles?: string[];
role_names?: string[];
permissions?: string[];
permission_names?: string[];
custom_claims?: Record<string, string>;
verified?: boolean;
// ...
};
// SessionData — what is stored in cookies
type SessionData = {
session: { uuid: string; expiry: number };
user: { uuid: string; first_name: string; last_name: string; email: string };
access_token: string;
refresh_token: string;
};FauthyClient Options
| Option | Type | Default | Description |
|---|---|---|---|
| secret | string | required | Secret key for cookie encryption |
| session_ttl | number | 2592000 (30 days) | Session lifetime in seconds |
| noAuthRedirectUrl | string | /api/auth/logout | Redirect URL when auth token cookie is missing |
