@zitadel/sdk-nuxt 0.1.0-alpha.9 → 1.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @zitadel/sdk-nuxt
2
2
 
3
- Nuxt middleware and helpers for Nextgen Auth.
3
+ Nuxt module, Nitro middleware, and helpers for Nextgen Auth.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,78 +8,97 @@ Nuxt middleware and helpers for Nextgen Auth.
8
8
  pnpm add @zitadel/sdk-nuxt
9
9
  ```
10
10
 
11
- ## Setup
11
+ There are two ways to wire the SDK. **The module is what `zitadel setup`
12
+ scaffolds** and the recommended path; the direct-middleware surface remains
13
+ for hand-rolled setups.
12
14
 
13
- ### 1. Server middleware
15
+ ## Surface 1 the Nuxt module (recommended, CLI-scaffolded)
14
16
 
15
- Create `server/middleware/auth.ts`:
16
-
17
- ```ts
18
- import { createNextgenMiddleware } from '@zitadel/sdk-nuxt/server';
19
-
20
- const { nextgen } = useRuntimeConfig();
21
-
22
- export default createNextgenMiddleware({
23
- url: nextgen.url,
24
- protectedRoutes: ['/admin', '/dashboard*'],
25
- loginPath: '/login',
26
- });
27
- ```
28
-
29
- The middleware runs on every request and does three things in one pass:
30
-
31
- 1. **Proxies** `/__nextgen/*` requests to the auth backend
32
- 2. **Verifies** the session JWT via JWKS using the Web Crypto API
33
- 3. **Redirects** unauthenticated requests to `loginPath` for protected routes
34
-
35
- Add the issuer URL to `nuxt.config.ts`:
17
+ Register the module under the `nextgen` config key, and give the client
18
+ plugin your project id via `runtimeConfig.public.zitadelProjectId` — without
19
+ it the plugin skips `configureZitadel()`, `useZitadelProject()` returns
20
+ `null`, and the login widget cannot initialize:
36
21
 
37
22
  ```ts
38
23
  export default defineNuxtConfig({
24
+ modules: ['@zitadel/sdk-nuxt/module'],
25
+ nextgen: {
26
+ url: process.env.ZITADEL_URL ?? 'http://localhost:8080',
27
+ protectedRoutes: ['/admin', '/dashboard*'],
28
+ loginPath: '/login',
29
+ },
39
30
  runtimeConfig: {
40
- nextgen: {
41
- url: process.env.ZITADEL_URL ?? 'http://localhost:4000',
31
+ public: {
32
+ zitadelProjectId: process.env.NUXT_PUBLIC_ZITADEL_PROJECT_ID ?? '',
42
33
  },
43
34
  },
44
35
  });
45
36
  ```
46
37
 
47
- ### 2. Plugin
38
+ (This mirrors what `zitadel setup` writes into `nuxt.config.ts`.)
48
39
 
49
- Create `plugins/auth.server.ts` to make auth state available in pages:
40
+ The module registers the Nitro server middleware, the auth plugin (which
41
+ seeds server-side auth state, hydrates it on the client, and calls
42
+ `configureZitadel()` from the runtime config above), and auto-imports the
43
+ composables — no `server/middleware/auth.ts`, no manual plugin.
50
44
 
51
- ```ts
52
- import { defineNuxtPlugin, useRequestEvent, useState } from '#imports';
53
-
54
- export default defineNuxtPlugin(() => {
55
- const event = useRequestEvent();
56
- const auth = event?.context.nextgenAuth ?? {
57
- isAuthenticated: false as const,
58
- session: null,
59
- };
60
- useState('nextgen-auth', () => auth);
61
- });
62
- ```
45
+ ### Module options (what the module actually forwards)
46
+
47
+ | Option | Type | Default | Description |
48
+ | --- | --- | --- | --- |
49
+ | `url` | `string` | `ZITADEL_URL` env, else `http://localhost:8080` | Full URL of the Zitadel auth backend |
50
+ | `proxyPath` | `string` | `"/__nextgen"` | The path the **client** widgets call (exposed via public runtime config). The registered server handler currently always serves `/__nextgen` regardless of this option — to actually move the server prefix, use the direct-middleware surface |
51
+ | `protectedRoutes` | `string[]` | `[]` | Paths requiring a valid session. Trailing `*` matches sub-paths |
52
+ | `loginPath` | `string` | `"/login"` | Where to redirect unauthenticated users |
63
53
 
64
- ### 3. Reading auth in a page
54
+ The module's registered handler reads only `url`, `protectedRoutes`, and
55
+ `loginPath` from runtime config; `proxyPath` configures the client side only
56
+ (see its row above). The fine-tuning options of the direct-middleware surface
57
+ (`ignoredRoutes`, `allowedAlgorithms`, `allowedTokenTypes`, `clockSkewMs`,
58
+ `jwksTimeoutMs`, `opaqueTokenTimeoutMs`, `proxyTimeoutMs`, `audience`) are
59
+ **not currently forwarded by the module** — if you need them, use Surface 2.
60
+ The module also loads the server-only project secret into runtime config at
61
+ startup, from the `ZITADEL_PROJECT_SECRET` environment variable or the
62
+ scaffolded `.env.local`.
63
+
64
+ ### Reading auth state
65
+
66
+ `useAuth()` is auto-imported:
65
67
 
66
68
  ```vue
67
69
  <script setup lang="ts">
68
- const auth = useState('nextgen-auth');
69
- if (auth.value?.isAuthenticated) {
70
- await navigateTo('/admin');
71
- }
70
+ const auth = useAuth();
72
71
  </script>
73
72
 
74
73
  <template>
75
- <p>{{ auth.isAuthenticated ? auth.session.email : 'Not signed in' }}</p>
74
+ <p>{{ auth.isAuthenticated ? (auth.session.display ?? auth.session.identifier) : 'Not signed in' }}</p>
76
75
  </template>
77
76
  ```
78
77
 
79
- ### 4. Register components (client only)
78
+ The returned state intentionally omits the raw JWT — use `getAuth(event)` in
79
+ a server route when you need the token to call upstream APIs:
80
+
81
+ ```ts
82
+ import { getAuth } from '@zitadel/sdk-nuxt/server';
83
+
84
+ export default defineEventHandler((event) => {
85
+ const auth = getAuth(event);
86
+ if (!auth.isAuthenticated) throw createError({ statusCode: 401 });
87
+ return { userId: auth.session.userId };
88
+ });
89
+ ```
90
+
91
+ ### Login page
92
+
93
+ Register the shared components in a client-only plugin
94
+ (`plugins/zitadel-components.client.ts` — do **not** import
95
+ `@zitadel/components` from page `<script setup>`, that runs during SSR).
96
+ Under strict package managers (pnpm, Yarn PnP) `@zitadel/components` is not
97
+ resolvable as a transitive dependency, so declare it in your app first:
80
98
 
81
- Create `plugins/zitadel-components.client.ts` — do **not** import
82
- `@zitadel/components` from page `<script setup>` (that runs during SSR):
99
+ ```bash
100
+ pnpm add @zitadel/components
101
+ ```
83
102
 
84
103
  ```ts
85
104
  import "@zitadel/components";
@@ -87,37 +106,48 @@ import "@zitadel/components";
87
106
  export default defineNuxtPlugin(() => {});
88
107
  ```
89
108
 
90
- Set `body { margin: 0; font-family: sans-serif; }` in `app.vue` (see
91
- [`apps/demo-nuxt`](../../apps/demo-nuxt/README.md)). Arimo loads from
92
- `branding.font_url` inside `<zitadel-login>` when the mock/API supplies it.
93
-
94
- ### 5. Login page
95
-
96
- Render `<zitadel-login>` inside `<ClientOnly>`:
109
+ Then render `<zitadel-login>` inside `<ClientOnly>`, binding the project
110
+ handle from the auto-imported `useZitadelProject()` composable there is no
111
+ `api-base` attribute:
97
112
 
98
113
  ```vue
114
+ <script setup lang="ts">
115
+ const project = useZitadelProject();
116
+ </script>
117
+
99
118
  <template>
100
119
  <main>
101
120
  <ClientOnly>
102
- <zitadel-login api-base="/__nextgen" project-id="demo" post-sign-in-url="/admin" />
121
+ <zitadel-login :project="project" post-sign-in-url="/admin" />
103
122
  </ClientOnly>
104
123
  </main>
105
124
  </template>
106
125
  ```
107
126
 
108
- ### 6. Reading auth in a server route
127
+ ## Surface 2 direct middleware (hand-rolled)
128
+
129
+ Create `server/middleware/auth.ts` yourself when you need the full option
130
+ set:
109
131
 
110
132
  ```ts
111
- import { getAuth } from '@zitadel/sdk-nuxt/server';
133
+ import { createNextgenMiddleware } from '@zitadel/sdk-nuxt/server';
112
134
 
113
- export default defineEventHandler((event) => {
114
- const auth = getAuth(event);
115
- if (!auth.isAuthenticated) throw createError({ statusCode: 401 });
116
- return { userId: auth.session.userId };
135
+ const { nextgen } = useRuntimeConfig();
136
+
137
+ export default createNextgenMiddleware({
138
+ url: nextgen.url,
139
+ protectedRoutes: ['/admin', '/dashboard*'],
140
+ loginPath: '/login',
117
141
  });
118
142
  ```
119
143
 
120
- ## Middleware options
144
+ The middleware runs on every request and does three things in one pass:
145
+
146
+ 1. **Proxies** `/__nextgen/*` requests to the auth backend
147
+ 2. **Verifies** the session JWT via JWKS using the Web Crypto API
148
+ 3. **Redirects** unauthenticated requests to `loginPath` for protected routes
149
+
150
+ ### Direct-middleware options
121
151
 
122
152
  | Option | Type | Default | Description |
123
153
  | ------------------- | -------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
@@ -130,17 +160,13 @@ export default defineEventHandler((event) => {
130
160
  | `allowedTokenTypes` | `string[]` | `["JWT", "at+JWT"]` | Accepted `typ` header values (case-insensitive). Set to `[]` to disable this check |
131
161
  | `clockSkewMs` | `number` | `5000` | Clock skew tolerance in ms for `exp`, `nbf`, `iat` |
132
162
  | `jwksTimeoutMs` | `number` | `5000` | Timeout in ms for JWKS endpoint requests. Token is rejected if the fetch exceeds this window |
163
+ | `opaqueTokenTimeoutMs` | `number` | `5000` | Timeout in ms for opaque (non-JWT) session validation via `GET /sessions/me` |
164
+ | `proxyTimeoutMs` | `number` | `5000` | Timeout in ms for upstream proxy requests; requests exceeding it abort with a network error |
133
165
  | `audience` | `string \| string[]` | not validated | Expected `aud` claim value(s). When omitted, audience is not checked |
134
166
 
135
167
  ## How JWT verification works
136
168
 
137
- 1. Bearer token from `Authorization` header is checked first; `__nextgen_session` cookie is the fallback
138
- 2. The JWT header is decoded to extract `kid` and `alg`
139
- 3. Tokens with an `alg` not in `allowedAlgorithms` (`RS256`, `ES256` by default) are rejected immediately — no JWKS fetch
140
- 4. Tokens with a `typ` not in `allowedTokenTypes` are rejected immediately
141
- 5. The public key is fetched from `{url}/auth/keys` (JWKS) using the Web Crypto API, with a 5 s timeout, and cached for 5 minutes per `kid`
142
- 6. The signature is verified **before** any claim checks
143
- 7. `iss` must be present and must equal `url` — tokens without an issuer are rejected
144
- 8. `exp` must be present and must be in the future (with `clockSkewMs` tolerance) — tokens without an expiry are rejected
145
- 9. `nbf` and `iat` are validated with `clockSkewMs` tolerance when present
146
- 10. The `x-nextgen-auth-token` header is stripped from all proxied requests to prevent internal state leakage
169
+ The verification pipeline is shared across SDKs and documented once in
170
+ [`@zitadel/sdk-core`](https://github.com/zitadel/nextgen/tree/main/packages/sdk-core#how-jwt-verification-works).
171
+ On top of it, the Nitro middleware strips the `x-nextgen-auth-token` header
172
+ from all proxied requests to prevent internal state leakage.
@@ -1,4 +1,5 @@
1
1
  // src/runtime/server/middleware.ts
2
+ import { useRuntimeConfig } from "#imports";
2
3
  import {
3
4
  HOP_BY_HOP,
4
5
  INTERNAL_HEADERS,
@@ -17,12 +18,7 @@ import {
17
18
  } from "h3";
18
19
 
19
20
  // src/runtime/lib/jwt.ts
20
- import {
21
- JWKS_TTL_MS,
22
- base64UrlDecode,
23
- decodeJwt,
24
- verifyJwt
25
- } from "@zitadel/sdk-core/jwt";
21
+ import { JWKS_TTL_MS, base64UrlDecode, decodeJwt, verifyJwt } from "@zitadel/sdk-core/jwt";
26
22
 
27
23
  // src/runtime/server/middleware.ts
28
24
  function buildUpstreamHeaders(event) {
@@ -38,10 +34,7 @@ function buildUpstreamHeaders(event) {
38
34
  const socketIp = event.node.req.socket?.remoteAddress;
39
35
  if (socketIp) {
40
36
  const existingXff = headers.get("x-forwarded-for");
41
- headers.set(
42
- "x-forwarded-for",
43
- existingXff ? `${existingXff}, ${socketIp}` : socketIp
44
- );
37
+ headers.set("x-forwarded-for", existingXff ? `${existingXff}, ${socketIp}` : socketIp);
45
38
  }
46
39
  if (!headers.has("x-forwarded-host")) {
47
40
  headers.set("x-forwarded-host", url.host);
@@ -64,8 +57,7 @@ function createNextgenMiddleware(options = {}) {
64
57
  allowedTokenTypes = ["JWT", "at+JWT"],
65
58
  jwksTimeoutMs,
66
59
  proxyTimeoutMs = 5e3,
67
- opaqueTokenTimeoutMs = 5e3,
68
- onExchangeResponse
60
+ opaqueTokenTimeoutMs = 5e3
69
61
  } = options;
70
62
  if (!loginPath.startsWith("/") || loginPath.startsWith("//")) {
71
63
  throw new Error(
@@ -80,14 +72,7 @@ function createNextgenMiddleware(options = {}) {
80
72
  return;
81
73
  }
82
74
  if (pathname === proxyPath || pathname.startsWith(`${proxyPath}/`)) {
83
- return proxyRequest(
84
- event,
85
- url,
86
- proxyPath,
87
- urlObj,
88
- proxyTimeoutMs,
89
- onExchangeResponse
90
- );
75
+ return proxyRequest(event, url, proxyPath, urlObj, proxyTimeoutMs);
91
76
  }
92
77
  return handleAuth(event, {
93
78
  url,
@@ -103,7 +88,7 @@ function createNextgenMiddleware(options = {}) {
103
88
  });
104
89
  });
105
90
  }
106
- async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs, onExchangeResponse) {
91
+ async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs) {
107
92
  const suffix = url.pathname.slice(proxyPath.length);
108
93
  const target = `${authUrl}${suffix}${url.search}`;
109
94
  const method = event.node.req.method ?? "GET";
@@ -111,11 +96,11 @@ async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs, onEx
111
96
  const rawBody = hasBody ? await readRawBody(event, false) : void 0;
112
97
  const body = rawBody != null ? new Uint8Array(rawBody) : void 0;
113
98
  const upstreamHeaders = buildUpstreamHeaders(event);
114
- const isExchangeRequest = method === "POST" && suffix.startsWith("/sessions/exchange");
115
- if (isExchangeRequest && !upstreamHeaders.has("authorization")) {
116
- const projectId = url.searchParams.get("project_id");
117
- if (projectId) {
118
- upstreamHeaders.set("authorization", `Bearer sk_${projectId}`);
99
+ if (requiresProjectSecret(method, suffix) && !upstreamHeaders.has("authorization")) {
100
+ const config = useRuntimeConfig();
101
+ const projectSecret = config.nextgen?.projectSecret;
102
+ if (projectSecret) {
103
+ upstreamHeaders.set("authorization", `Bearer ${projectSecret}`);
119
104
  }
120
105
  }
121
106
  const upstream = await fetch(target, {
@@ -130,14 +115,10 @@ async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs, onEx
130
115
  for (const cookie of setCookieHeaders) {
131
116
  responseHeaders.append("set-cookie", cookie);
132
117
  }
133
- let response = new Response(upstream.body, {
118
+ const response = new Response(upstream.body, {
134
119
  status: upstream.status,
135
120
  headers: responseHeaders
136
121
  });
137
- const isExchange = method === "POST" && suffix.startsWith("/sessions/exchange");
138
- if (isExchange && onExchangeResponse) {
139
- response = await onExchangeResponse(response);
140
- }
141
122
  event.node.res.statusCode = response.status;
142
123
  for (const [key, value] of response.headers.entries()) {
143
124
  if (key.toLowerCase() === "set-cookie") continue;
@@ -149,14 +130,15 @@ async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs, onEx
149
130
  }
150
131
  return response.body;
151
132
  }
133
+ function requiresProjectSecret(method, pathname) {
134
+ return method.toUpperCase() === "POST" && pathname === "/sessions/exchange";
135
+ }
152
136
  var DECODER = new TextDecoder();
153
137
  function isJwtShaped(token) {
154
138
  const parts = token.split(".");
155
139
  if (parts.length < 3 || !parts[0]) return false;
156
140
  try {
157
- const header = JSON.parse(
158
- DECODER.decode(base64UrlDecode(parts[0]))
159
- );
141
+ const header = JSON.parse(DECODER.decode(base64UrlDecode(parts[0])));
160
142
  return typeof header?.alg === "string" && !("enc" in header);
161
143
  } catch {
162
144
  return false;
@@ -171,7 +153,12 @@ async function validateOpaqueSessionToken(token, issuerUrl, timeoutMs) {
171
153
  });
172
154
  if (!res.ok) return null;
173
155
  const body = await res.json();
174
- return { userId: body.user_id };
156
+ return {
157
+ userId: body.user_id,
158
+ identifier: body.user?.identifier ?? null,
159
+ identifierProperty: body.user?.identifier_property ?? null,
160
+ display: body.user?.display ?? null
161
+ };
175
162
  } catch {
176
163
  return null;
177
164
  }
@@ -207,36 +194,38 @@ async function handleAuth(event, opts) {
207
194
  isAuthenticated: true,
208
195
  session: {
209
196
  userId: payload.sub,
210
- email: payload.email ?? null,
211
- name: payload.name ?? null,
197
+ identifier: payload.email ?? null,
198
+ identifierProperty: null,
199
+ display: payload.name ?? null,
212
200
  token
213
201
  }
214
202
  };
215
203
  return;
216
204
  }
205
+ let liveAnonymousSession = false;
217
206
  if (!payload && cookieToken && !isJwtShaped(cookieToken)) {
218
- const opaqueResult = await validateOpaqueSessionToken(
219
- cookieToken,
220
- url,
221
- opaqueTokenTimeoutMs
222
- );
223
- if (opaqueResult) {
207
+ const opaqueResult = await validateOpaqueSessionToken(cookieToken, url, opaqueTokenTimeoutMs);
208
+ if (opaqueResult?.userId) {
224
209
  event.context.nextgenAuth = {
225
210
  isAuthenticated: true,
226
211
  session: {
227
- userId: opaqueResult.userId ?? "unknown",
228
- email: null,
229
- name: null,
212
+ userId: opaqueResult.userId,
213
+ identifier: opaqueResult.identifier,
214
+ identifierProperty: opaqueResult.identifierProperty,
215
+ display: opaqueResult.display,
230
216
  token: cookieToken
231
217
  }
232
218
  };
233
219
  return;
234
220
  }
221
+ liveAnonymousSession = opaqueResult !== null;
235
222
  }
236
223
  event.context.nextgenAuth = { isAuthenticated: false, session: null };
237
- for (const name of Object.keys(parseCookies(event))) {
238
- if (name.startsWith("__nextgen")) {
239
- deleteCookie(event, name);
224
+ if (!liveAnonymousSession) {
225
+ for (const name of Object.keys(parseCookies(event))) {
226
+ if (name.startsWith("__nextgen")) {
227
+ deleteCookie(event, name);
228
+ }
240
229
  }
241
230
  }
242
231
  if (matchesRoutes(pathname, protectedRoutes)) {
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- export { ZitadelLogin, ZitadelLogout } from '@zitadel/components';
1
+ export { ZitadelLogin, ZitadelLogout, businessLocales } from '@zitadel/components';
2
2
  export { createNextgenMiddleware, getAuth } from './runtime/server/middleware.js';
3
3
  import { ZitadelProject } from '@zitadel/api/config';
4
- export { ClientAuthResult } from './runtime/types.js';
5
- export { AuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/types';
4
+ export { AuthResult, ClientAuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/middleware';
6
5
  import 'h3';
7
6
 
8
7
  /**
package/dist/index.js CHANGED
@@ -2,10 +2,11 @@ import "./chunk-ZNXAFGLP.js";
2
2
  import {
3
3
  createNextgenMiddleware,
4
4
  getAuth
5
- } from "./chunk-E7GMYXBM.js";
5
+ } from "./chunk-GQKD27DF.js";
6
6
 
7
7
  // src/index.ts
8
8
  import { ZitadelLogin, ZitadelLogout } from "@zitadel/components";
9
+ import { businessLocales } from "@zitadel/components";
9
10
 
10
11
  // src/runtime/composables/useZitadelProject.ts
11
12
  import { getZitadelConfig } from "@zitadel/api/config";
@@ -15,6 +16,7 @@ function useZitadelProject() {
15
16
  export {
16
17
  ZitadelLogin,
17
18
  ZitadelLogout,
19
+ businessLocales,
18
20
  createNextgenMiddleware,
19
21
  getAuth,
20
22
  useZitadelProject
package/dist/module.js CHANGED
@@ -6,6 +6,27 @@ import {
6
6
  addImportsDir,
7
7
  createResolver
8
8
  } from "@nuxt/kit";
9
+ import { existsSync, readFileSync } from "fs";
10
+ import { resolve as resolvePath } from "path";
11
+ function loadProjectSecret(rootDir) {
12
+ if (process.env.ZITADEL_PROJECT_SECRET) {
13
+ return process.env.ZITADEL_PROJECT_SECRET;
14
+ }
15
+ const path = resolvePath(rootDir, ".env.local");
16
+ if (!existsSync(path)) {
17
+ return void 0;
18
+ }
19
+ for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
20
+ const match = line.match(/^\s*(?:export\s+)?ZITADEL_PROJECT_SECRET\s*=\s*(.*)$/);
21
+ if (match && match[1] !== void 0) {
22
+ const raw = match[1].trim();
23
+ const quoted = raw.match(/^(['"])(.*)\1\s*(?:#.*)?$/);
24
+ const value = quoted ? quoted[2] : raw.replace(/\s+#.*$/, "").trim();
25
+ return value === "" ? void 0 : value;
26
+ }
27
+ }
28
+ return void 0;
29
+ }
9
30
  var module_default = defineNuxtModule({
10
31
  meta: {
11
32
  name: "@zitadel/sdk-nuxt",
@@ -23,7 +44,12 @@ var module_default = defineNuxtModule({
23
44
  url: options.url ?? "http://localhost:4000",
24
45
  loginPath: options.loginPath ?? "/login",
25
46
  protectedRoutes: options.protectedRoutes ?? [],
26
- jwtKey: options.jwtKey
47
+ jwtKey: options.jwtKey,
48
+ // Server-only — never exposed to the client. Override at deploy time via
49
+ // `NUXT_NEXTGEN_PROJECT_SECRET`. Left undefined when the env var (and
50
+ // `.env.local`) provide no value, so the middleware surfaces a missing
51
+ // exchange bearer instead of silently sending an empty one.
52
+ projectSecret: loadProjectSecret(nuxt.options.rootDir)
27
53
  };
28
54
  nuxt.options.runtimeConfig.public.zitadelProxyPath = options.proxyPath ?? "/__nextgen";
29
55
  nuxt.options.runtimeConfig.public.nextgenProxyPath = options.proxyPath ?? "/__nextgen";
@@ -1,10 +1,5 @@
1
1
  // src/runtime/plugin.ts
2
- import {
3
- defineNuxtPlugin,
4
- useRequestEvent,
5
- useRuntimeConfig,
6
- useState
7
- } from "#imports";
2
+ import { defineNuxtPlugin, useRequestEvent, useRuntimeConfig, useState } from "#imports";
8
3
  import { configureZitadel } from "@zitadel/api/config";
9
4
  var plugin_default = defineNuxtPlugin(() => {
10
5
  const event = useRequestEvent();
@@ -16,8 +11,9 @@ var plugin_default = defineNuxtPlugin(() => {
16
11
  isAuthenticated: true,
17
12
  session: {
18
13
  userId: auth.session.userId,
19
- email: auth.session.email,
20
- name: auth.session.name
14
+ identifier: auth.session.identifier,
15
+ identifierProperty: auth.session.identifierProperty,
16
+ display: auth.session.display
21
17
  }
22
18
  } : { isAuthenticated: false, session: null };
23
19
  useState("nextgen-auth", () => clientAuth);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createNextgenMiddleware
3
- } from "../../chunk-E7GMYXBM.js";
3
+ } from "../../chunk-GQKD27DF.js";
4
4
 
5
5
  // src/runtime/server/handler.ts
6
6
  import { useRuntimeConfig } from "#imports";
@@ -1,7 +1,7 @@
1
- import { AuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/types';
1
+ import { AuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/middleware';
2
2
  import { EventHandler, H3Event } from 'h3';
3
3
 
4
- declare module 'h3' {
4
+ declare module "h3" {
5
5
  interface H3EventContext {
6
6
  nextgenAuth: AuthResult;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createNextgenMiddleware,
3
3
  getAuth
4
- } from "../../chunk-E7GMYXBM.js";
4
+ } from "../../chunk-GQKD27DF.js";
5
5
  export {
6
6
  createNextgenMiddleware,
7
7
  getAuth
@@ -1,37 +1 @@
1
- import { UnauthState } from '@zitadel/sdk-core/types';
2
- export { AuthResult, AuthState, NextgenMiddlewareOptions, NextgenSession, UnauthState } from '@zitadel/sdk-core/types';
3
-
4
- /**
5
- * Re-exports shared SDK types from `@zitadel/sdk-core`.
6
- *
7
- * These types are defined once in sdk-core and shared by both sdk-next
8
- * and sdk-nuxt.
9
- */
10
-
11
- /**
12
- * The client-safe session exposed to Vue components via {@link useAuth}.
13
- * Identical to {@link NextgenSession} but omits `token` — the raw JWT must
14
- * not be serialised into the Nuxt SSR payload where third-party scripts can
15
- * read it.
16
- */
17
- type ClientSession = {
18
- /** The user's unique identifier (`sub` claim). */
19
- userId: string;
20
- /** The user's email address, or `null` if not present in the token. */
21
- email: string | null;
22
- /** The user's display name, or `null` if not present in the token. */
23
- name: string | null;
24
- };
25
- /** Client-safe auth state when the user is signed in. */
26
- type ClientAuthState = {
27
- isAuthenticated: true;
28
- session: ClientSession;
29
- };
30
- /**
31
- * Union of all possible auth states returned by {@link useAuth}.
32
- * Token is intentionally absent — use {@link getAuth} server-side when the
33
- * raw JWT is needed.
34
- */
35
- type ClientAuthResult = ClientAuthState | UnauthState;
36
-
37
- export type { ClientAuthResult, ClientAuthState, ClientSession };
1
+ export { AuthResult, AuthState, ClientAuthResult, ClientAuthState, ClientSession, NextgenMiddlewareOptions, NextgenSession, UnauthState } from '@zitadel/sdk-core/middleware';
package/dist/server.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { createNextgenMiddleware, getAuth } from './runtime/server/middleware.js';
2
- import '@zitadel/sdk-core/types';
2
+ import '@zitadel/sdk-core/middleware';
3
3
  import 'h3';
package/dist/server.js CHANGED
@@ -2,7 +2,7 @@ import "./chunk-ZNXAFGLP.js";
2
2
  import {
3
3
  createNextgenMiddleware,
4
4
  getAuth
5
- } from "./chunk-E7GMYXBM.js";
5
+ } from "./chunk-GQKD27DF.js";
6
6
  export {
7
7
  createNextgenMiddleware,
8
8
  getAuth
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zitadel/sdk-nuxt",
3
- "version": "0.1.0-alpha.9",
4
- "description": "Nuxt proxy middleware and helpers for Nextgen Auth",
3
+ "version": "1.0.0-alpha.21",
4
+ "description": "Nuxt proxy middleware and helpers for the pre-release Zitadel preview.",
5
5
  "homepage": "https://github.com/zitadel/nextgen/tree/main/packages/sdk-nuxt#readme",
6
6
  "bugs": {
7
7
  "url": "https://github.com/zitadel/nextgen/issues"
@@ -33,9 +33,9 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@zitadel/components": "0.1.0-alpha.9",
37
- "@zitadel/api": "0.1.0-alpha.9",
38
- "@zitadel/sdk-core": "0.1.0-alpha.9"
36
+ "@zitadel/api": "1.0.0-alpha.21",
37
+ "@zitadel/sdk-core": "1.0.0-alpha.21",
38
+ "@zitadel/components": "1.0.0-alpha.21"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "h3": ">=1",
@@ -53,6 +53,7 @@
53
53
  "eslint-plugin-perfectionist": "^4.0.0",
54
54
  "eslint-plugin-prettier": "^5.0.0",
55
55
  "h3": "^1.15.3",
56
+ "nuxt": "^4.5.1",
56
57
  "prettier": "^3.0.0",
57
58
  "tsup": "^8.3.5",
58
59
  "typescript": "^5.7.3",