Quickstarts · next-js
Next.js — Hub-backed SSO in 5 minutes
Add OAuth 2.0 / OIDC login to a Next.js 15 App Router app via Hub. Five steps, ~30 lines of code.
- next-js
- react
- oidc
- app-router
Tested against:framework: Next.js 15.3hubSdk: @thoryn/sdk@1.0.0nextAuth: next-auth@5.0.0-beta
Prereqs
- Next.js 15+ App Router app (this works on 14 too with minor tweaks)
- Node 20+
- A Thoryn account + Hub admin access
Step 1 — Register a client in Hub
hub clients create \
--name "My Next.js app" \
--redirect-uri "http://localhost:3000/api/auth/callback/thoryn" \
--grant-types authorization_code,refresh_token \
--scopes "openid email profile"Capture the client_id and client_secret.
Step 2 — Install dependencies
npm install next-auth@betaStep 3 — Configure auth
auth.ts:
import NextAuth from "next-auth";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
{
id: "thoryn",
name: "Thoryn",
type: "oidc",
issuer: "https://hub.thoryn.org",
clientId: process.env.THORYN_CLIENT_ID,
clientSecret: process.env.THORYN_CLIENT_SECRET,
},
],
});app/api/auth/[...nextauth]/route.ts:
export { GET, POST } from "@/auth";Step 4 — Render the user
app/page.tsx:
import { auth, signIn, signOut } from "@/auth";
export default async function Home() {
const session = await auth();
if (!session) {
return (
<form action={async () => { "use server"; await signIn("thoryn"); }}>
<button type="submit">Sign in with Thoryn</button>
</form>
);
}
return (
<div>
<p>Hello, {session.user?.name}</p>
<form action={async () => { "use server"; await signOut(); }}>
<button type="submit">Sign out</button>
</form>
</div>
);
}Step 5 — Run it
THORYN_CLIENT_ID=... THORYN_CLIENT_SECRET=... npm run devOpen http://localhost:3000, click Sign in with Thoryn, you should land back logged in.
What's next
- Hub — How it works — full token flow, refresh-token families, Vault Transit
- Recipe: role-admin — gate routes by claim
- Recipe: mfa-required-for-priv-actions — step-up
Troubleshooting
- 401 from
/api/auth/callback/thoryn: redirect URI mismatch. Double-check the URI in Hub admin matches exactly (/api/auth/callback/thoryn, not/api/auth/callback). sessionis null after login: cookie domain mismatch. SetAUTH_URLto your origin.