From 7a03aae9b22723d34b6fadbe3e9e5f5ed678f4e1 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Tue, 12 May 2026 11:26:01 +0300 Subject: [PATCH 01/37] feat: harmonize project configuration --- package.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8b36a1d..dafe804 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ "node": ">=22.0.0" }, "scripts": { - "dev": "next dev", "build": "next build", - "prepack": "tsc --noEmit", - "start": "next dev", - "lint": "eslint .", + "dev": "next dev", "format": "prettier --write .", "format:check": "prettier --check .", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "prepack": "tsc --noEmit", + "start": "next dev", "test": "playwright test" }, "dependencies": { From 8ed562792651603b6b4eb683deb815b262b666cf Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Tue, 12 May 2026 11:50:17 +0300 Subject: [PATCH 02/37] feat: harmonize project configuration --- package.json | 4 +- public/openid-logo.svg | 87 ++++++++++++------------- public/robots.txt | 2 + public/zitadel-logo.svg | 139 ++++++++++++++-------------------------- 4 files changed, 94 insertions(+), 138 deletions(-) create mode 100644 public/robots.txt diff --git a/package.json b/package.json index dafe804..45542b9 100644 --- a/package.json +++ b/package.json @@ -35,13 +35,13 @@ "@types/node": "^22", "@types/react": "^19", "@types/react-dom": "^19", - "eslint": "^9", + "eslint": "^9.39.1", "eslint-config-next": "^16", "eslint-config-prettier": "^10.1.8", "knip": "^5.64.1", "postcss": "^8.5.10", "prettier": "^3.6.2", "tailwindcss": "^4", - "typescript": "^5" + "typescript": "~5.9.2" } } diff --git a/public/openid-logo.svg b/public/openid-logo.svg index 9b7f80f..666c013 100644 --- a/public/openid-logo.svg +++ b/public/openid-logo.svg @@ -1,57 +1,52 @@ - - - - - - - - + + + + + + + + - - - - - - - - + id="path2210" /> \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..0ad279c --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-Agent: * +Disallow: diff --git a/public/zitadel-logo.svg b/public/zitadel-logo.svg index 268b58b..95ff801 100644 --- a/public/zitadel-logo.svg +++ b/public/zitadel-logo.svg @@ -1,142 +1,101 @@ - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - + + + + + + + From 8d795f5a34a414b9b63deb9cb8af9463e2830247 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Tue, 12 May 2026 13:57:09 +0300 Subject: [PATCH 03/37] feat: harmonize project configuration --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index 8418336..cfcca19 100644 --- a/.prettierignore +++ b/.prettierignore @@ -29,3 +29,4 @@ node_modules *.jpeg *.gif *.svg + From 727804bf103188a35fc071cad8135e1f6d81d8c1 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 15:41:12 +0300 Subject: [PATCH 04/37] feat: replace next-auth v4 with @zitadel/next-auth --- package.json | 3 ++- src/app/api/auth/[...nextauth]/route.ts | 7 ++----- src/app/api/auth/logout/route.ts | 8 ++++---- src/app/api/userinfo/route.ts | 7 +++---- src/app/auth/login/page.tsx | 9 ++++----- src/app/page.tsx | 2 +- src/app/profile/page.tsx | 2 +- src/app/providers.tsx | 2 +- src/lib/auth.ts | 16 +++++++++------- 9 files changed, 27 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 45542b9..c3347b2 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,9 @@ "test": "playwright test" }, "dependencies": { + "@auth/core": "^0.40.0", + "@zitadel/next-auth": "^0.1.0", "next": "^16.2.6", - "next-auth": "^4.24.13", "openid-client": "^6.6.2", "react": "^19", "react-dom": "^19" diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 0a4c217..753116f 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,6 +1,3 @@ -import NextAuth from 'next-auth'; -import { authOptions } from '@/lib/auth'; +import { handlers } from '''@/lib/auth'''; -const handler = NextAuth(authOptions); - -export { handler as GET, handler as POST }; +export const { GET, POST } = handlers; diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index dd6d6ab..73f39ac 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from 'next/server'; -import { getServerSession } from 'next-auth/next'; -import { authOptions, buildLogoutUrl } from '@/lib/auth'; +import { auth } from '@/lib/auth'; +import { buildLogoutUrl } from '@/lib/auth'; /** * Initiates the logout process by redirecting the user to the external Identity @@ -15,8 +15,8 @@ import { authOptions, buildLogoutUrl } from '@/lib/auth'; * response if no valid session exists. The response includes a secure state cookie * that will be validated in the logout callback. */ -export async function POST() { - const session = await getServerSession(authOptions); +export async function POST(request: Request) { + const session = await auth(request as Request); if (!session?.idToken) { return NextResponse.json( diff --git a/src/app/api/userinfo/route.ts b/src/app/api/userinfo/route.ts index 576589c..8364b06 100644 --- a/src/app/api/userinfo/route.ts +++ b/src/app/api/userinfo/route.ts @@ -1,5 +1,4 @@ -import { getServerSession } from 'next-auth/next'; -import { authOptions } from '@/lib/auth'; +import { auth } from '@/lib/auth'; import { NextResponse } from 'next/server'; /** @@ -20,8 +19,8 @@ import { NextResponse } from 'next/server'; * * Extended user profile with ZITADEL-specific claims like roles and metadata. */ -export async function GET(): Promise { - const session = await getServerSession(authOptions); +export async function GET(request: Request): Promise { + const session = await auth(request as Request); if (!session?.accessToken) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index 873db31..cb2ad15 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -3,10 +3,9 @@ import { getProviders, getCsrfToken, - ClientSafeProvider, - LiteralUnion, -} from 'next-auth/react'; -import { BuiltInProviderType } from 'next-auth/providers/index'; + type ClientSafeProvider, +} from '@zitadel/next-auth/react'; +import type { BuiltInProviderType } from '@auth/core/providers'; import { useSearchParams } from 'next/navigation'; import { useEffect, useState } from 'react'; import Link from 'next/link'; @@ -19,7 +18,7 @@ function SignInContent() { const callbackUrl = searchParams.get('callbackUrl'); const [providers, setProviders] = useState, + string, ClientSafeProvider > | null>(null); const [csrfToken, setCsrfToken] = useState(''); diff --git a/src/app/page.tsx b/src/app/page.tsx index 50f5860..d4b56b0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { signIn } from 'next-auth/react'; +import { signIn } from '@zitadel/next-auth/react'; import { Header } from '@/components/Header'; import { Footer } from '@/components/Footer'; import Image from 'next/image'; diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index 2dcc790..f608d8d 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -1,7 +1,7 @@ 'use client'; import { useEffect } from 'react'; -import { signIn, useSession } from 'next-auth/react'; +import { signIn, useSession } from '@zitadel/next-auth/react'; import { Header } from '@/components/Header'; import { Footer } from '@/components/Footer'; diff --git a/src/app/providers.tsx b/src/app/providers.tsx index f3517b2..557d815 100644 --- a/src/app/providers.tsx +++ b/src/app/providers.tsx @@ -1,6 +1,6 @@ 'use client'; -import { SessionProvider } from 'next-auth/react'; +import { SessionProvider } from '@zitadel/next-auth/react'; import React from 'react'; export function ZitadelProvider({ children }: { children: React.ReactNode }) { diff --git a/src/lib/auth.ts b/src/lib/auth.ts index cc5a717..ed8996c 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,8 +1,8 @@ -import { NextAuthOptions } from 'next-auth'; -import ZitadelProvider from 'next-auth/providers/zitadel'; +import { type NextAuthConfig, NextAuth } from '@zitadel/next-auth'; +import Zitadel from '@auth/core/providers/zitadel'; import { randomUUID } from 'crypto'; import * as oidc from 'openid-client'; -import { JWT } from 'next-auth/jwt'; +import type { JWT } from '@auth/core/jwt'; import { ZITADEL_SCOPES } from './scopes'; /** @@ -120,7 +120,7 @@ export async function buildLogoutUrl( * This makes ZITADEL tokens available throughout your application via the * useSession() hook and getServerSession() function. */ -declare module 'next-auth' { +declare module '@auth/core/types' { // noinspection JSUnusedGlobalSymbols interface Session { /** The OpenID Connect ID token from ZITADEL - used for logout and user identification */ @@ -138,7 +138,7 @@ declare module 'next-auth' { * This internal interface stores tokens securely in the encrypted JWT that * NextAuth uses for session management. */ -declare module 'next-auth/jwt' { +declare module '@auth/core/jwt' { // noinspection JSUnusedGlobalSymbols interface JWT { /** The OpenID Connect ID token from ZITADEL */ @@ -189,9 +189,9 @@ declare module 'next-auth/jwt' { * - **jwt**: Manages token storage and refresh logic * - **session**: Shapes what data is available to your app */ -export const authOptions: NextAuthOptions = { +export const authOptions: NextAuthConfig = { providers: [ - ZitadelProvider({ + Zitadel({ issuer: process.env.ZITADEL_DOMAIN!, clientId: process.env.ZITADEL_CLIENT_ID!, clientSecret: process.env.ZITADEL_CLIENT_SECRET!, @@ -388,3 +388,5 @@ export const authOptions: NextAuthOptions = { }, }, }; + +export const { handlers, auth } = NextAuth(authOptions); From d09999b1b1f1019810765d64f125be73bb1a339d Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 16:14:56 +0300 Subject: [PATCH 05/37] fix: align scaffold files with parity standards --- knip.config.js | 7 ++++++- playwright.config.ts | 1 + prettier.config.mjs | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/knip.config.js b/knip.config.js index 28100d9..8fb8e43 100644 --- a/knip.config.js +++ b/knip.config.js @@ -1,4 +1,9 @@ -export default { +module.exports = { ignoreDependencies: ['@commitlint/config-conventional'], + entry: [ + 'src/app/**/*', + 'src/components/**/*', + 'src/lib/**/*', + ], ignore: ['commitlint.config.js'], }; diff --git a/playwright.config.ts b/playwright.config.ts index ec4f5d9..7990e4e 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -15,6 +15,7 @@ const testEnv = { NEXTAUTH_SECRET: 'test-nextauth-secret-for-e2e-tests', }; +// noinspection JSUnusedGlobalSymbols export default defineConfig({ testDir: './test', outputDir: './build/test-results', diff --git a/prettier.config.mjs b/prettier.config.mjs index 98d2f6a..a32c23b 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-anonymous-default-export export default { semi: true, trailingComma: 'all', @@ -6,4 +5,6 @@ export default { printWidth: 80, tabWidth: 2, useTabs: false, + plugins: ['prettier-plugin-tailwindcss'], + tailwindStylesheet: './src/app/globals.css', }; From 0bfd591906b5aeb554b5b862aad29a2a9bc9f5f2 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 16:20:40 +0300 Subject: [PATCH 06/37] fix: align devcontainer and gitignore with canonical scaffold --- .devcontainer/devcontainer.json | 2 +- .gitignore | 53 +++++++++++++-------------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4099401..07942ed 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -11,7 +11,7 @@ "otherPortsAttributes": { "onAutoForward": "silent" }, - "onCreateCommand": "cp -n .env.example .env.local", + "onCreateCommand": "cp -n .env.example .env", "updateContentCommand": "npm ci", "postCreateCommand": "npx playwright install --with-deps chromium", "customizations": { diff --git a/.gitignore b/.gitignore index 5ef6a52..548c688 100644 --- a/.gitignore +++ b/.gitignore @@ -1,41 +1,28 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +node_modules +.npm -# dependencies -/node_modules -/.pnp -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/versions - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production +# Output +.output +.next +.vercel +.netlify +.wrangler +/.svelte-kit /build -# misc +# OS .DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* +Thumbs.db -# env files (can opt-in for committing if needed) -.env* +# Env +.env +.env.* +!.env.example +!.env.test -# vercel -.vercel +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* -# typescript -*.tsbuildinfo +# Next.js generated types next-env.d.ts From 3a37a773d9ef6d99593645c4c061ae3650138872 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 16:29:27 +0300 Subject: [PATCH 07/37] fix: route devcontainer commands through devbox to use project-local npm cache --- .devcontainer/devcontainer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 07942ed..e10de9c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,9 @@ { "name": "Zitadel Example Next.js Auth", "image": "mcr.microsoft.com/devcontainers/javascript-node:22-bookworm", + "features": { + "ghcr.io/jetify-com/devcontainer-feature/devbox:latest": {} + }, "forwardPorts": [3000], "portsAttributes": { "3000": { @@ -12,8 +15,8 @@ "onAutoForward": "silent" }, "onCreateCommand": "cp -n .env.example .env", - "updateContentCommand": "npm ci", - "postCreateCommand": "npx playwright install --with-deps chromium", + "updateContentCommand": "devbox run npm ci", + "postCreateCommand": "devbox run npx playwright install --with-deps chromium", "customizations": { "vscode": { "extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] From 66c625146df1afc17f57ef7d80175a49f0973069 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 22:26:32 +0300 Subject: [PATCH 08/37] fix: add missing prettier-plugin-tailwindcss devDependency --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c3347b2..e82ba9a 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "knip": "^5.64.1", "postcss": "^8.5.10", "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^4", "typescript": "~5.9.2" } From 273524d4df466001df1cfab714063f7e9607c5b8 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 22:35:11 +0300 Subject: [PATCH 09/37] fix: add depcheck script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e82ba9a..2d03f6a 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "format:check": "prettier --check .", "lint": "eslint .", "lint:fix": "eslint . --fix", + "depcheck": "npx knip", "prepack": "tsc --noEmit", "start": "next dev", "test": "playwright test" From 516bd15b391b9b5cd9523fbe8016bb77645a7d67 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 22:42:12 +0300 Subject: [PATCH 10/37] fix: ignore tsconfig.tsbuildinfo --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 548c688..6346fab 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ vite.config.ts.timestamp-* # Next.js generated types next-env.d.ts + +# TypeScript build info +tsconfig.tsbuildinfo From a223c2d4bf1ce3024f3d6c854f3e0de2cee5589b Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 22:50:28 +0300 Subject: [PATCH 11/37] fix: remove version field to match canonical --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 2d03f6a..e5bda08 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "name": "example-nextjs-auth", "license": "Apache-2.0", - "version": "0.1.0", "type": "module", "private": true, "engines": { From eb32620b4d97093ba09418907e785a15ce286e5e Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 23:11:04 +0300 Subject: [PATCH 12/37] chore: add trailing newline to .nvmrc --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 92f279e..53d1c14 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v22 \ No newline at end of file +v22 From 1985e4f488ceddbe33531cd4726c0fbe206ad591 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 23:17:18 +0300 Subject: [PATCH 13/37] chore: add .devbox/ to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 6346fab..4f5f321 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ next-env.d.ts # TypeScript build info tsconfig.tsbuildinfo + +# Devbox +.devbox/ From 31eabba1729959652fd254b58f0a88fc6f4e1378 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 23:54:09 +0300 Subject: [PATCH 14/37] fix: correct git clone URL in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a8e905d..7640f00 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ Follow these steps to get the application running: ```bash # 1. Clone the repository -git clone git@github.com:zitadel/example-auth-nextjs.git +git clone git@github.com:zitadel/example-nextjs-auth.git -cd example-auth-nextjs +cd example-nextjs-auth # 2. Install the project dependencies npm install From 9f2bda03f89315bf914419b6758c6037c747e29d Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Fri, 15 May 2026 23:55:56 +0300 Subject: [PATCH 15/37] revert: restore correct git clone URL (remote is example-auth-nextjs) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7640f00..a8e905d 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ Follow these steps to get the application running: ```bash # 1. Clone the repository -git clone git@github.com:zitadel/example-nextjs-auth.git +git clone git@github.com:zitadel/example-auth-nextjs.git -cd example-nextjs-auth +cd example-auth-nextjs # 2. Install the project dependencies npm install From d94f11cf1edd9fd6f770e560b4b52ea4f9f91b9a Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Mon, 18 May 2026 17:18:56 +0300 Subject: [PATCH 16/37] feat: integrate @zitadel/next-auth and refactor auth routes --- .env.example | 9 + knip.config.js | 10 +- package-lock.json | 374 ++++++++++++++---------- package.json | 12 +- playwright.config.ts | 3 +- prettier.config.mjs | 1 + src/app/api/auth/[...nextauth]/route.ts | 3 +- src/app/api/auth/logout/route.ts | 5 +- src/app/api/userinfo/route.ts | 5 +- src/app/auth/error/page.tsx | 5 +- src/app/auth/login/page.tsx | 16 +- src/app/layout.tsx | 3 +- src/app/logout/error/page.tsx | 5 +- src/app/logout/success/page.tsx | 5 +- src/app/not-found.tsx | 5 +- src/app/page.tsx | 54 ++-- src/app/profile/page.tsx | 57 ++-- src/components/ErrorBoundary.tsx | 5 +- src/components/Footer.tsx | 9 +- src/components/Header.tsx | 7 +- src/components/SignOutButton.tsx | 3 +- src/lib/auth.ts | 282 +----------------- test/app.spec.ts | 2 +- tsconfig.json | 17 +- 24 files changed, 357 insertions(+), 540 deletions(-) diff --git a/.env.example b/.env.example index dfbf11f..df6a6be 100644 --- a/.env.example +++ b/.env.example @@ -66,3 +66,12 @@ ZITADEL_POST_LOGOUT_URL="http://localhost:3000/api/auth/logout/callback" # Auth.js requires this to create secure callback and redirect links. # This is optional for local development but REQUIRED for production. NEXTAUTH_URL="http://localhost:3000" + +# Auth.js base URL alias. Some Auth.js adapters read AUTH_URL as a fallback +# for the base URL. Set this to the same value as NEXTAUTH_URL. +AUTH_URL="http://localhost:3000" + +# Secret key used by NextAuth.js to sign and encrypt JWTs and session cookies. +# Generate a secure key using: +# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +NEXTAUTH_SECRET="your-very-secret-and-strong-nextauth-key" diff --git a/knip.config.js b/knip.config.js index 8fb8e43..55d8764 100644 --- a/knip.config.js +++ b/knip.config.js @@ -1,9 +1,9 @@ module.exports = { - ignoreDependencies: ['@commitlint/config-conventional'], - entry: [ - 'src/app/**/*', - 'src/components/**/*', - 'src/lib/**/*', + ignoreDependencies: [ + '@commitlint/config-conventional', + '@zitadel/next-auth', + 'globals', ], + entry: ['src/app/**/*', 'src/components/**/*', 'src/lib/**/*'], ignore: ['commitlint.config.js'], }; diff --git a/package-lock.json b/package-lock.json index 6375d4d..7164401 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,35 +6,76 @@ "packages": { "": { "name": "example-nextjs-auth", - "version": "0.1.0", "license": "Apache-2.0", "dependencies": { + "@auth/core": "^0.41.0", + "@zitadel/next-auth": "file:../next-auth", "next": "^16.2.6", - "next-auth": "^4.24.13", - "openid-client": "^6.6.2", + "openid-client": "^6.6.3", "react": "^19", "react-dom": "^19" }, "devDependencies": { "@commitlint/config-conventional": "^20.5.0", "@playwright/test": "^1.56.1", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.0.0", "@types/node": "^22", "@types/react": "^19", "@types/react-dom": "^19", - "eslint": "^9", + "eslint": "^9.39.1", "eslint-config-next": "^16", "eslint-config-prettier": "^10.1.8", + "globals": "^16.3.0", "knip": "^5.64.1", "postcss": "^8.5.10", "prettier": "^3.6.2", - "tailwindcss": "^4", - "typescript": "^5" + "prettier-plugin-tailwindcss": "^0.6.14", + "tailwindcss": "^4.0.0", + "typescript": "~5.9.2" }, "engines": { "node": ">=22.0.0" } }, + "../next-auth": { + "name": "@zitadel/next-auth", + "version": "0.1.0", + "license": "Apache-2.0", + "devDependencies": { + "@auth/core": "^0.40.0", + "@commitlint/config-conventional": "^20.5.0", + "@jest/globals": "^30.0.5", + "@mridang/eslint-defaults": "^1.6.1", + "@semantic-release/commit-analyzer": "^13.0.1", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^12.0.0", + "@semantic-release/npm": "^13.1.5", + "@semantic-release/release-notes-generator": "^14.1.0", + "@tsconfig/node22": "^22.0.2", + "@types/jest": "^30.0.0", + "@types/node": "^22.18.13", + "@types/react": "^19.0.0", + "eslint": "9.32.0", + "jest": "30.0.5", + "jest-junit": "^17.0.0", + "knip": "^5.66.4", + "prettier": "3.6.2", + "semantic-release": "^25.0.3", + "ts-jest": "29.4.0", + "tsup": "^8.5.0", + "typedoc": "^0.28.7", + "typescript": "^5.9.3" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "@auth/core": ">=0.40.0", + "next": ">=15.0.0", + "react": ">=19.0.0", + "react-dom": ">=19.0.0" + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -48,6 +89,63 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@auth/core": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.2.tgz", + "integrity": "sha512-Hx5MNBxN2fJTbJKGUKAA0wca43D0Akl3TvufY54Gn8lop7F+34vU1zA1pn0vQfIoVuLIrpfc2nkyjwIaPJMW7w==", + "license": "ISC", + "dependencies": { + "@panva/hkdf": "^1.2.1", + "jose": "^6.0.6", + "oauth4webapi": "^3.3.0", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" + }, + "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.2", + "nodemailer": "^7.0.7" + }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/@auth/core/node_modules/jose": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/@auth/core/node_modules/preact": { + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/@auth/core/node_modules/preact-render-to-string": { + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", + "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", + "license": "MIT", + "peerDependencies": { + "preact": ">=10" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -240,15 +338,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -465,6 +554,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { "version": "9.39.4", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", @@ -2542,6 +2644,10 @@ "win32" ] }, + "node_modules/@zitadel/next-auth": { + "resolved": "../next-auth", + "link": true + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -3090,15 +3196,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -4133,6 +4230,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4288,9 +4386,9 @@ } }, "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -4967,15 +5065,6 @@ "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5690,71 +5779,6 @@ } } }, - "node_modules/next-auth": { - "version": "4.24.14", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.14.tgz", - "integrity": "sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig==", - "license": "ISC", - "dependencies": { - "@babel/runtime": "^7.20.13", - "@panva/hkdf": "^1.0.2", - "cookie": "^0.7.0", - "jose": "^4.15.5", - "oauth": "^0.9.15", - "openid-client": "^5.4.0", - "preact": "^10.6.3", - "preact-render-to-string": "^5.1.19", - "uuid": "^8.3.2" - }, - "peerDependencies": { - "@auth/core": "0.34.3", - "next": "^12.2.5 || ^13 || ^14 || ^15 || ^16", - "nodemailer": "^7.0.7", - "react": "^17.0.2 || ^18 || ^19", - "react-dom": "^17.0.2 || ^18 || ^19" - }, - "peerDependenciesMeta": { - "@auth/core": { - "optional": true - }, - "nodemailer": { - "optional": true - } - } - }, - "node_modules/next-auth/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/next-auth/node_modules/openid-client": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", - "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", - "license": "MIT", - "dependencies": { - "jose": "^4.15.9", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/next-auth/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/node-exports-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", @@ -5781,12 +5805,6 @@ "dev": true, "license": "MIT" }, - "node_modules/oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==", - "license": "MIT" - }, "node_modules/oauth4webapi": { "version": "3.8.5", "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.5.tgz", @@ -5806,15 +5824,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -5928,15 +5937,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oidc-token-hash": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz", - "integrity": "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw==", - "license": "MIT", - "engines": { - "node": "^10.13.0 || >=12.0.0" - } - }, "node_modules/openid-client": { "version": "6.8.3", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.3.tgz", @@ -6188,28 +6188,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/preact": { - "version": "10.29.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", - "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/preact-render-to-string": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", - "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", - "license": "MIT", - "dependencies": { - "pretty-format": "^3.8.0" - }, - "peerDependencies": { - "preact": ">=10" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6236,11 +6214,92 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", - "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==", - "license": "MIT" + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz", + "integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "@zackad/prettier-plugin-twig": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + } + } }, "node_modules/prop-types": { "version": "15.8.1", @@ -7278,15 +7337,6 @@ "punycode": "^2.1.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/walk-up-path": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", diff --git a/package.json b/package.json index e5bda08..b0ba338 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,15 @@ "lint:fix": "eslint . --fix", "depcheck": "npx knip", "prepack": "tsc --noEmit", + "preview": "next start", "start": "next dev", "test": "playwright test" }, "dependencies": { - "@auth/core": "^0.40.0", - "@zitadel/next-auth": "^0.1.0", + "@auth/core": "^0.41.0", + "@zitadel/next-auth": "file:../next-auth", "next": "^16.2.6", - "openid-client": "^6.6.2", + "openid-client": "^6.6.3", "react": "^19", "react-dom": "^19" }, @@ -32,18 +33,19 @@ "devDependencies": { "@commitlint/config-conventional": "^20.5.0", "@playwright/test": "^1.56.1", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.0.0", "@types/node": "^22", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9.39.1", "eslint-config-next": "^16", "eslint-config-prettier": "^10.1.8", + "globals": "^16.3.0", "knip": "^5.64.1", "postcss": "^8.5.10", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", - "tailwindcss": "^4", + "tailwindcss": "^4.0.0", "typescript": "~5.9.2" } } diff --git a/playwright.config.ts b/playwright.config.ts index 7990e4e..a9ea9e5 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -8,8 +8,9 @@ const testEnv = { ZITADEL_DOMAIN: 'https://test.zitadel.cloud', ZITADEL_CLIENT_ID: 'test-client-id', ZITADEL_CLIENT_SECRET: 'test-client-secret', - ZITADEL_CALLBACK_URL: 'http://localhost:3000/api/auth/callback', + ZITADEL_CALLBACK_URL: 'http://localhost:3000/api/auth/callback/zitadel', ZITADEL_POST_LOGOUT_URL: 'http://localhost:3000/api/auth/logout/callback', + ZITADEL_POST_LOGIN_URL: '/profile', AUTH_URL: 'http://localhost:3000', NEXTAUTH_URL: 'http://localhost:3000', NEXTAUTH_SECRET: 'test-nextauth-secret-for-e2e-tests', diff --git a/prettier.config.mjs b/prettier.config.mjs index a32c23b..9a8bf50 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -1,3 +1,4 @@ +/** @type {import("prettier").Config} */ export default { semi: true, trailingComma: 'all', diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 753116f..85f29f0 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,3 +1,4 @@ -import { handlers } from '''@/lib/auth'''; +// noinspection JSUnusedGlobalSymbols +import { handlers } from '@/lib/auth'; export const { GET, POST } = handlers; diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 73f39ac..1d8cda0 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,5 +1,6 @@ +// noinspection JSUnusedGlobalSymbols import { NextResponse } from 'next/server'; -import { auth } from '@/lib/auth'; +import { getSession } from '@/lib/auth'; import { buildLogoutUrl } from '@/lib/auth'; /** @@ -16,7 +17,7 @@ import { buildLogoutUrl } from '@/lib/auth'; * that will be validated in the logout callback. */ export async function POST(request: Request) { - const session = await auth(request as Request); + const session = await getSession(request as Request); if (!session?.idToken) { return NextResponse.json( diff --git a/src/app/api/userinfo/route.ts b/src/app/api/userinfo/route.ts index 8364b06..6fec6d5 100644 --- a/src/app/api/userinfo/route.ts +++ b/src/app/api/userinfo/route.ts @@ -1,4 +1,5 @@ -import { auth } from '@/lib/auth'; +// noinspection JSUnusedGlobalSymbols +import { getSession } from '@/lib/auth'; import { NextResponse } from 'next/server'; /** @@ -20,7 +21,7 @@ import { NextResponse } from 'next/server'; * Extended user profile with ZITADEL-specific claims like roles and metadata. */ export async function GET(request: Request): Promise { - const session = await auth(request as Request); + const session = await getSession(request as Request); if (!session?.accessToken) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); diff --git a/src/app/auth/error/page.tsx b/src/app/auth/error/page.tsx index 8e2132a..9dd0bcf 100644 --- a/src/app/auth/error/page.tsx +++ b/src/app/auth/error/page.tsx @@ -1,3 +1,4 @@ +// noinspection JSUnusedGlobalSymbols 'use client'; import Link from 'next/link'; @@ -12,9 +13,9 @@ function AuthErrorContent() { const { heading, message } = getMessage(error, 'auth-error'); return ( -
+
-
+
+

Loading…

@@ -49,9 +49,9 @@ function SignInContent() { const provider = providers?.zitadel; return ( -
-
-
+
+
+
-

+

What happens when you click the button:

-
+
- + 1 Generate code verifier & challenge
- + 2 Redirect to Zitadel authorization
- + 3 Exchange code for tokens
- + Access granted securely @@ -171,6 +172,7 @@ export default function Home() { Learn more about PKCE diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index f608d8d..10bfd37 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -1,3 +1,4 @@ +// noinspection JSUnusedGlobalSymbols 'use client'; import { useEffect } from 'react'; @@ -16,22 +17,22 @@ export default function ProfilePage() { if (status === 'loading') { return ( -
+

Loading your session…

); } return ( -
+
-
-
+
+
-
+
@@ -46,40 +47,40 @@ export default function ProfilePage() {

Authentication Successful!

-

+

You have successfully completed the PKCE authentication flow.

-
-

+
+

🔐 OAuth 2.0 PKCE Flow Completed

-

+

Congratulations! You have successfully completed the OAuth 2.0 PKCE (Proof Key for Code Exchange) authentication flow. This demonstrates how modern applications securely authenticate users with Zitadel.

-
+
-

+

What is PKCE?

-

+

PKCE is a security extension to OAuth 2.0 that protects against authorization code interception attacks. It's especially important for public clients like single-page applications and mobile apps.

-

+

Key Benefits:

  • @@ -93,7 +94,7 @@ export default function ProfilePage() {
  • @@ -107,7 +108,7 @@ export default function ProfilePage() {
  • @@ -122,12 +123,12 @@ export default function ProfilePage() {
-

+

Flow Steps Completed

-
+
@@ -140,7 +141,7 @@ export default function ProfilePage() {
-
+
@@ -153,7 +154,7 @@ export default function ProfilePage() {
-
+
@@ -166,7 +167,7 @@ export default function ProfilePage() {
-
+
@@ -179,7 +180,7 @@ export default function ProfilePage() {
-
+
@@ -195,16 +196,16 @@ export default function ProfilePage() {
-
-

+
+

Session Information

-

+

Below is the authentication data stored in your session after a successful PKCE flow:

-
-
+            
+
                 {JSON.stringify(session, null, 2)}
               
diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index 48d3f47..0427510 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -48,6 +48,7 @@ interface State { * * ``` */ +// noinspection JSUnusedGlobalSymbols export class ErrorBoundary extends Component { constructor(props: Props) { super(props); @@ -82,9 +83,9 @@ export class ErrorBoundary extends Component { } return ( -
+
-
+
-
+