Nuxt Quickstart
This is step 4 of the getting started sequence. By the end you will have a working Nuxt 3 app with sign-in and sign-out powered by ThunderID.
What You Will Learn
- Create a new Nuxt 3 app
- Register the
@thunderid/nuxtmodule
- Add working sign-in and sign-out
- Display the signed-in user's profile
Prerequisites
- About 15 minutes
- Steps 1–3 complete: ThunderID running, an application registered, and a sign-in flow built. Start at Get ThunderID if you haven't already.
- Node.js 18.0 or later installed on your system
- npm, yarn, or pnpm
- Your preferred code editor
Create an Application in ThunderID
Before integrating ThunderID with your Nuxt app, you need to create an application in ThunderID.
The @thunderid/nuxt module automatically registers a /api/auth/callback server route that handles the OAuth callback. Your redirect URL must point to this route.
Using the ThunderID Console
- Sign into the ThunderID Console at https://localhost:8090/console
- Navigate to Applications → New Application
- Provide the following details:
- Name:
my-nuxt-app - Type: Web Application
- Authorized Redirect URL:
http://localhost:3000/api/auth/callback
- Name:
The SDK automatically registers /api/auth/callback as a Nitro server route. You do not need to create this file yourself.
Using the ThunderID API
You can also create an application using the ThunderID API. First, obtain a system API token, then:
curl -kL -X POST https://localhost:8090/applications \
-H 'Authorization: Bearer <your-system-token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "my-nuxt-app",
"inboundAuthConfig": [{
"type": "oauth2",
"config": {
"grantTypes": ["authorization_code", "refresh_token"],
"responseTypes": ["code"],
"redirectUris": ["http://localhost:3000/api/auth/callback"],
"tokenEndpointAuthMethod": "client_secret_post",
"publicClient": false,
"pkceRequired": true
}
}]
}'
Note down both the Client ID and Client Secret from the response. You'll need both to configure your Nuxt app.
Create a Nuxt App
Create a new Nuxt 3 app:
npm
pnpm
Yarn
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
pnpm dlx nuxi@latest init my-nuxt-app
cd my-nuxt-app
pnpm install
yarn dlx nuxi@latest init my-nuxt-app
cd my-nuxt-app
yarn install
Install @thunderid/nuxt
Install the ThunderID Nuxt module:
npm
pnpm
Yarn
Bun
npm install @thunderid/nuxt
pnpm add @thunderid/nuxt
yarn add @thunderid/nuxt
bun add @thunderid/nuxt
Register the Module
Add @thunderid/nuxt to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@thunderid/nuxt'],
});
That's all the nuxt.config.ts change needed — the module reads all configuration from environment variables.
Set Up Environment Variables
Create a .env file in the root of your project:
NUXT_PUBLIC_THUNDERID_BASE_URL=https://localhost:8090
NUXT_PUBLIC_THUNDERID_CLIENT_ID=<your-client-id>
THUNDERID_CLIENT_SECRET=<your-client-secret>
THUNDERID_SESSION_SECRET=<your-session-secret>
Run the following command to generate a strong random secret for THUNDERID_SESSION_SECRET:
openssl rand -base64 32
THUNDERID_CLIENT_SECRET and THUNDERID_SESSION_SECRET have no NUXT_PUBLIC_ prefix — Nuxt keeps them server-side only and never exposes them to the browser.
| Variable | Description |
|---|---|
NUXT_PUBLIC_THUNDERID_BASE_URL | Your ThunderID instance URL |
NUXT_PUBLIC_THUNDERID_CLIENT_ID | The Client ID from your ThunderID application |
THUNDERID_CLIENT_SECRET | The Client Secret (server-side only) |
THUNDERID_SESSION_SECRET | Secret for signing session JWT cookies (server-side only) |
Wrap Your App with ThunderIDRoot
The <ThunderIDRoot> component mounts the full authentication provider tree. Wrap your application content with it in app.vue:
<template>
<ThunderIDRoot>
<NuxtPage />
</ThunderIDRoot>
</template>
The @thunderid/nuxt module auto-registers all components and auto-imports all composables. You do not need to import them manually.
Add Sign-In and Sign-Out
The module provides <SignedIn>, <SignedOut>, <SignInButton>, and <SignOutButton> components for conditional rendering and authentication actions.
Create pages/index.vue:
<template>
<main>
<header>
<h1>ThunderID Auth Demo</h1>
<SignedIn>
<SignOutButton>Sign Out</SignOutButton>
</SignedIn>
<SignedOut>
<SignInButton>Sign In</SignInButton>
</SignedOut>
</header>
</main>
</template>
Display User Profile Information
Use <User> with a scoped slot to access and display profile information for the signed-in user:
<template>
<main>
<header>
<h1>ThunderID Auth Demo</h1>
<SignedIn>
<SignOutButton>Sign Out</SignOutButton>
</SignedIn>
<SignedOut>
<SignInButton>Sign In</SignInButton>
</SignedOut>
</header>
<section>
<SignedIn>
<User>
<template #default="{ user }">
<div class="user-profile">
<img
v-if="user.picture"
:src="user.picture"
:alt="user.name || 'User avatar'"
style="width: 80px; height: 80px; border-radius: 50%"
/>
<h2>Welcome, {{ user.name || user.username }}!</h2>
<div>
<p><strong>Email:</strong> {{ user.email }}</p>
<p><strong>First Name:</strong> {{ user.given_name }}</p>
<p><strong>Last Name:</strong> {{ user.family_name }}</p>
</div>
</div>
</template>
</User>
</SignedIn>
</section>
</main>
</template>
Protect a Page
To require authentication on a page, add the built-in 'thunderIDMiddleware' route middleware:
<script setup>
definePageMeta({ middleware: ['thunderIDMiddleware'] });
</script>
Unauthenticated users are automatically redirected to the sign-in page. For more control — such as requiring specific scopes or an organization context — use defineThunderIDMiddleware:
<script setup>
const protect = defineThunderIDMiddleware({ requireOrganization: true });
definePageMeta({ middleware: [protect] });
</script>
Run Your App
Start the development server:
npm
pnpm
Yarn
npm run dev
pnpm run dev
yarn dev
Visit your app at http://localhost:3000
You should see the sign-in button. Click it — you'll be redirected to the ThunderID-hosted sign-in page, authenticate with the test user you created in step 2, and land back in your app with the user profile displayed.
You're Done
You have completed the full getting started sequence:
- ✅ ThunderID running
- ✅ Application registered with a Client ID and Client Secret
- ✅ Sign-in flow built in the Flow Designer
- ✅ Nuxt 3 app integrated and authenticating