Skip to main content

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/nextjs package
  • 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
1

Run ThunderID

Start a local ThunderID instance. Pick the method that works best for you:

$npx thunderid

Requires Node.js 18+

Full install guide →

Once it's running, the console is available at https://localhost:8090/console.

2

Create an Application

  1. Sign in to the Console.

    Test User

    If you used the default setup, sign in to the Console as admin with the password generated during setup and printed to the setup output (unless you supplied your own).

  2. Navigate to Applications.

  3. Click Add Application.

  4. From the Choose a type page, select Next.js.

  5. Enter a name (e.g. My Next.js App).

  6. Select how you want to sign in users (e.g., email/password, social login, etc.).

  7. Select Theme settings.

  8. Leave Sign-In Approach set to Bring Your Own UI (the default for Next.js applications).

  9. Click Create.

Note

Copy the Application ID from the General tab, under Quick Copy. Also copy the Flow Secret from the window that pops up when the application is created; it's shown only once (if lost, regenerate it from the application's Credentials tab).

3

Create a Next.js App

Create your new Next.js app:

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app

When prompted, select the App Router option (the default).

4

Install @thunderid/nextjs

Install the ThunderID Next.js SDK in your project:

npm install @thunderid/nextjs
5

Set Environment Variables

Create a .env file in your project root with the following:

Configuration

Replace <your-application-id> and <your-flow-secret> with the values from your ThunderID application.

Generate a random string for THUNDERID_SECRET (at least 32 characters):

openssl rand -base64 32
.env
NEXT_PUBLIC_THUNDERID_BASE_URL=https://localhost:8090
NEXT_PUBLIC_THUNDERID_APPLICATION_ID=<your-application-id>
THUNDERID_FLOW_SECRET=<your-flow-secret>
NEXT_PUBLIC_THUNDERID_SIGN_IN_URL=/signin
NEXT_PUBLIC_THUNDERID_SIGN_UP_URL=/signup
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
6

Add ThunderIDProvider to Your Layout

Wrap your root layout with ThunderIDProvider from the server export. This enables authentication across your entire app.

app/layout.tsx
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>
);
}
7

Add the ThunderID Proxy

Create a proxy.ts file at your project root to proxy requests through ThunderID and protect routes:

proxy.ts
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).*)'],
}
8

Add Sign-In and Sign-Up Pages

The <SignIn /> and <SignUp /> components render the sign-in and sign-up forms natively, using the Flow Execution API. Create the routes configured above as NEXT_PUBLIC_THUNDERID_SIGN_IN_URL and NEXT_PUBLIC_THUNDERID_SIGN_UP_URL:

app/signin/page.tsx
"use client";
import { useRouter } from "next/navigation";
import { SignIn } from "@thunderid/nextjs";

export default function SignInPage() {
const router = useRouter();

return (
<section className="flex flex-col items-center justify-center min-h-screen py-2">
<SignIn onSuccess={() => router.push("/")} />
</section>
);
}
app/signup/page.tsx
"use client";
import { SignUp } from "@thunderid/nextjs";

export default function SignUpPage() {
return (
<section className="flex flex-col items-center justify-center min-h-screen py-2">
<SignUp afterSignUpUrl="/" />
</section>
);
}
9

Build with ThunderID components

Update your home page with ThunderID authentication components:

app/page.tsx
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>
);
}
info

<SignInButton /> navigates to the local NEXT_PUBLIC_THUNDERID_SIGN_IN_URL route you created above, rather than redirecting to a ThunderID-hosted page.

10

Run Your App

Start the development server:

npm run dev

Visit your app at http://localhost:3000

Success

You should see the sign-in button. Click it, you'll land on your application's own /signin page. Authenticate with the test user you created in step 2, then return to your application with the user dropdown displayed.

What's Next

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.