Next.js Quickstart
Use this guide to add ThunderID authentication to a Next.js application using the @thunderid/nextjs SDK with full App Router support.
What You Will Learn
- Create a new Next.js app
- Install the
@thunderid/nextjspackage
- Add working sign-in and sign-out
- Protect routes with middleware
Prerequisites
- About 15 minutes
- Node.js installed on your system
- npm, yarn, or pnpm
- Your preferred code editor
Run ThunderID
Start a local ThunderID instance. Pick the method that works best for you:
Requires Node.js 18+
Full install guide →Once it's running, the console is available at https://localhost:8090.
Create an Application
Open the Console at https://localhost:8090/console, navigate to Applications, and click Add Application:
- Under Technology, select Next.js.
- Enter a name (e.g.
My Next.js App) and create an application. The rest of the settings can stay at their defaults. - Copy both the Client ID and Client Secret from the window that pops up. The Client ID can also be found in the General tab.
- Under General, add
http://localhost:3000to the list of Authorized Redirect URIs.
Create a Next.js App
Create your new Next.js app:
npm
Yarn
pnpm
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
yarn create next-app my-nextjs-app
cd my-nextjs-app
pnpm create next-app my-nextjs-app
cd my-nextjs-app
When prompted, select the App Router option (the default).
Install @thunderid/nextjs
Install the ThunderID Next.js SDK in your project:
npm
Yarn
pnpm
npm install @thunderid/nextjs
yarn add @thunderid/nextjs
pnpm add @thunderid/nextjs
Set Environment Variables
Create a .env.local file in your project root with the following:
Replace <your-client-id> and <your-client-secret> with the values from your ThunderID application.
Generate a random string for THUNDERID_SECRET (at least 32 characters):
openssl rand -base64 32
NEXT_PUBLIC_THUNDERID_BASE_URL=https://localhost:8090
NEXT_PUBLIC_THUNDERID_CLIENT_ID=<your-client-id>
THUNDERID_CLIENT_SECRET=<your-client-secret>
THUNDERID_SECRET=<a-random-secret-for-session-signing>
# DANGER: Disables ALL TLS verification. Only for local development with self-signed certs. NEVER use in production.
NODE_TLS_REJECT_UNAUTHORIZED=0
Add ThunderIDProvider to Your Layout
Wrap your root layout with ThunderIDProvider from the server export. This enables authentication across your entire app.
ThunderIDProvider handles the OAuth callback automatically — no manual callback route is needed. Make sure the authorized redirect URL in your ThunderID application settings is set to http://localhost:3000.
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { ThunderIDProvider } from '@thunderid/nextjs/server'
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">
<ThunderIDProvider>{children}</ThunderIDProvider>
</body>
</html>
);
}
Add the ThunderID Proxy
Create a proxy.ts file at your project root to proxy requests through ThunderID and protect routes:
import {
thunderIDProxy,
createRouteMatcher,
} from '@thunderid/nextjs/server'
const isProtectedRoute = createRouteMatcher([
// Add the paths you want to protect, e.g. '/dashboard(.*)'
])
export default thunderIDProxy(async (thunderid, request) => {
if (isProtectedRoute(request)) {
await thunderid.protectRoute()
}
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
Build with ThunderID components
Update your home page with ThunderID authentication components:
import { SignedIn, UserDropdown, SignedOut, SignInButton } from "@thunderid/nextjs";
export default function Home() {
return (
<section className="flex flex-col items-center justify-center min-h-screen py-2">
<SignedIn>
<UserDropdown />
</SignedIn>
<SignedOut>
<SignInButton>Sign In</SignInButton>
</SignedOut>
</section>
);
}
Run Your App
Start the development server:
npm
Yarn
pnpm
npm run dev
yarn dev
pnpm dev
Visit your app at http://localhost:3000
You should see the sign-in button. Click it to be redirected to the ThunderID-hosted sign-in page. Authenticate with the test user you created in step 2, then return to your app with the user dropdown displayed.