Radon
Framework Integrations

Next.js

Mount Radon in a Next.js App Router app — one catch-all route, plus helpers to read the user in route handlers, server components, and middleware.

Radon's Next.js integration is one handler you export from a catch-all route, plus helpers to read the current user anywhere you have a Request.

Prerequisites

A configured auth instance (Installation) and at least one auth method enabled. App Router (the app/ directory).

1. Mount the auth routes

Create a catch-all route and export the handler for both GET and POST.

app/api/auth/[...radon]/route.ts
import { radonNextHandler } from "@radonsdk/auth/integrations/next";
import { auth } from "@/lib/auth";

const handler = radonNextHandler(auth, { basePath: "/api/auth" });

export const GET = handler;
export const POST = handler;

That single file serves every auth route under /api/auth (see each method for its routes).

Handler options

radonNextHandler(auth, {
  basePath: "/api/auth",              // must match the route folder
  cookieName: "acme_session",          // default "radon_session"
  cookieOptions: { domain: ".acme.com", sameSite: "lax" },
  successRedirect: "/dashboard",       // after magic-link / OAuth callback
  failureRedirect: "/signin?error=1",
});

2. Read the user in a route handler

getUserFromRequest verifies the session cookie and loads the user, or returns null.

app/api/me/route.ts
import { getUserFromRequest } from "@radonsdk/auth/integrations/next";
import { auth } from "@/lib/auth";

export async function GET(req: Request) {
  const user = await getUserFromRequest(auth, req);
  if (!user) return new Response("Unauthorized", { status: 401 });
  return Response.json({ user });
}

3. Read the user in a Server Component

Server Components don't get a Request, so build one from next/headers:

app/dashboard/page.tsx
import { headers } from "next/headers";
import { getUserFromRequest } from "@radonsdk/auth/integrations/next";
import { redirect } from "next/navigation";
import { auth } from "@/lib/auth";

export default async function Dashboard() {
  const req = new Request("http://local/", { headers: await headers() });
  const user = await getUserFromRequest(auth, req);
  if (!user) redirect("/signin");
  return <h1>Welcome, {user.email}</h1>;
}

4. Gate routes in middleware

For a cheap check with no database hit, getSessionClaims verifies just the JWT signature and returns the claims (claims.sub is the user id).

middleware.ts
import { NextResponse } from "next/server";
import { getSessionClaims } from "@radonsdk/auth/integrations/next";
import { auth } from "@/lib/auth";

export function middleware(req: Request) {
  const claims = getSessionClaims(auth, req);
  if (!claims) return NextResponse.redirect(new URL("/signin", req.url));
  return NextResponse.next();
}

export const config = { matcher: ["/dashboard/:path*"] };

Claims vs. user

getSessionClaims is signature-only (fast, edge-safe) — use it to gate. When you need the actual user record, use getUserFromRequest (one DB read).

CSRF for your own endpoints

Radon's auth routes are protected, but for your own state-changing POST routes you can use the double-submit helpers:

import { issueCsrfToken, verifyCsrfToken } from "@radonsdk/auth/integrations/next";

Next steps

On this page