@zitadel/sdk-nuxt 0.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ZITADEL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @zitadel/sdk-nuxt
2
+
3
+ Nuxt middleware and helpers for Nextgen Auth.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @zitadel/sdk-nuxt
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ### 1. Server middleware
14
+
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`:
36
+
37
+ ```ts
38
+ export default defineNuxtConfig({
39
+ runtimeConfig: {
40
+ nextgen: {
41
+ url: process.env.ZITADEL_URL ?? 'http://localhost:4000',
42
+ },
43
+ },
44
+ });
45
+ ```
46
+
47
+ ### 2. Plugin
48
+
49
+ Create `plugins/auth.server.ts` to make auth state available in pages:
50
+
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
+ ```
63
+
64
+ ### 3. Reading auth in a page
65
+
66
+ ```vue
67
+ <script setup lang="ts">
68
+ const auth = useState('nextgen-auth');
69
+ if (auth.value?.isAuthenticated) {
70
+ await navigateTo('/admin');
71
+ }
72
+ </script>
73
+
74
+ <template>
75
+ <p>{{ auth.isAuthenticated ? auth.session.email : 'Not signed in' }}</p>
76
+ </template>
77
+ ```
78
+
79
+ ### 4. Register components (client only)
80
+
81
+ Create `plugins/zitadel-components.client.ts` — do **not** import
82
+ `@zitadel/components` from page `<script setup>` (that runs during SSR):
83
+
84
+ ```ts
85
+ import "@zitadel/components";
86
+
87
+ export default defineNuxtPlugin(() => {});
88
+ ```
89
+
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>`:
97
+
98
+ ```vue
99
+ <template>
100
+ <main>
101
+ <ClientOnly>
102
+ <zitadel-login api-base="/__nextgen" project-id="demo" post-sign-in-url="/admin" />
103
+ </ClientOnly>
104
+ </main>
105
+ </template>
106
+ ```
107
+
108
+ ### 6. Reading auth in a server route
109
+
110
+ ```ts
111
+ import { getAuth } from '@zitadel/sdk-nuxt/server';
112
+
113
+ export default defineEventHandler((event) => {
114
+ const auth = getAuth(event);
115
+ if (!auth.isAuthenticated) throw createError({ statusCode: 401 });
116
+ return { userId: auth.session.userId };
117
+ });
118
+ ```
119
+
120
+ ## Middleware options
121
+
122
+ | Option | Type | Default | Description |
123
+ | ------------------- | -------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
124
+ | `url` | `string` | `ZITADEL_URL` env | Full URL of the Zitadel auth backend |
125
+ | `proxyPath` | `string` | `"/__nextgen"` | Path prefix proxied to the auth backend |
126
+ | `protectedRoutes` | `string[]` | `[]` | Paths requiring a valid session. Trailing `*` matches sub-paths |
127
+ | `ignoredRoutes` | `string[]` | `[]` | Paths skipped entirely — no JWT check, no tunnelling. Useful for webhooks or health checks. Trailing `*` matches sub-paths |
128
+ | `loginPath` | `string` | `"/login"` | Where to redirect unauthenticated users |
129
+ | `allowedAlgorithms` | `string[]` | `["RS256", "ES256"]` | JWT `alg` values to accept. Tokens with any other algorithm are rejected before JWKS is fetched |
130
+ | `allowedTokenTypes` | `string[]` | `["JWT", "at+JWT"]` | Accepted `typ` header values (case-insensitive). Set to `[]` to disable this check |
131
+ | `clockSkewMs` | `number` | `5000` | Clock skew tolerance in ms for `exp`, `nbf`, `iat` |
132
+ | `jwksTimeoutMs` | `number` | `5000` | Timeout in ms for JWKS endpoint requests. Token is rejected if the fetch exceeds this window |
133
+ | `audience` | `string \| string[]` | not validated | Expected `aud` claim value(s). When omitted, audience is not checked |
134
+
135
+ ## How JWT verification works
136
+
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
@@ -0,0 +1,199 @@
1
+ // src/runtime/server/middleware.ts
2
+ import {
3
+ HOP_BY_HOP,
4
+ INTERNAL_HEADERS,
5
+ filterResponseHeaders,
6
+ matchesRoutes
7
+ } from "@zitadel/sdk-core/middleware";
8
+ import {
9
+ defineEventHandler,
10
+ getCookie,
11
+ parseCookies,
12
+ deleteCookie,
13
+ sendRedirect,
14
+ getRequestURL,
15
+ getRequestHeader,
16
+ readRawBody
17
+ } from "h3";
18
+
19
+ // src/runtime/lib/jwt.ts
20
+ import {
21
+ JWKS_TTL_MS,
22
+ base64UrlDecode,
23
+ decodeJwt,
24
+ verifyJwt
25
+ } from "@zitadel/sdk-core/jwt";
26
+
27
+ // src/runtime/server/middleware.ts
28
+ function buildUpstreamHeaders(event) {
29
+ const headers = new Headers();
30
+ for (const [key, value] of Object.entries(event.node.req.headers)) {
31
+ const lower = key.toLowerCase();
32
+ if (!value || HOP_BY_HOP.has(lower) || INTERNAL_HEADERS.has(lower)) {
33
+ continue;
34
+ }
35
+ headers.set(key, Array.isArray(value) ? value.join(", ") : value);
36
+ }
37
+ const url = getRequestURL(event);
38
+ const socketIp = event.node.req.socket?.remoteAddress;
39
+ if (socketIp) {
40
+ const existingXff = headers.get("x-forwarded-for");
41
+ headers.set(
42
+ "x-forwarded-for",
43
+ existingXff ? `${existingXff}, ${socketIp}` : socketIp
44
+ );
45
+ }
46
+ if (!headers.has("x-forwarded-host")) {
47
+ headers.set("x-forwarded-host", url.host);
48
+ }
49
+ if (!headers.has("x-forwarded-proto")) {
50
+ headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
51
+ }
52
+ return headers;
53
+ }
54
+ function createNextgenMiddleware(options = {}) {
55
+ const {
56
+ url = process.env.ZITADEL_URL ?? "http://localhost:8080",
57
+ proxyPath = "/__nextgen",
58
+ protectedRoutes = [],
59
+ ignoredRoutes = [],
60
+ loginPath = "/login",
61
+ allowedAlgorithms = ["RS256", "ES256"],
62
+ clockSkewMs = 5e3,
63
+ audience,
64
+ allowedTokenTypes = ["JWT", "at+JWT"],
65
+ jwksTimeoutMs,
66
+ proxyTimeoutMs = 5e3,
67
+ onExchangeResponse
68
+ } = options;
69
+ if (!loginPath.startsWith("/") || loginPath.startsWith("//")) {
70
+ throw new Error(
71
+ `[nextgen] loginPath must be a relative path starting with a single "/". Received: "${loginPath}". Using an absolute or protocol-relative URL would allow open-redirect attacks.`
72
+ );
73
+ }
74
+ return defineEventHandler(async (event) => {
75
+ const urlObj = getRequestURL(event);
76
+ const { pathname } = urlObj;
77
+ if (matchesRoutes(pathname, ignoredRoutes)) {
78
+ delete event.node.req.headers["x-nextgen-auth-token"];
79
+ return;
80
+ }
81
+ if (pathname === proxyPath || pathname.startsWith(`${proxyPath}/`)) {
82
+ return proxyRequest(
83
+ event,
84
+ url,
85
+ proxyPath,
86
+ urlObj,
87
+ proxyTimeoutMs,
88
+ onExchangeResponse
89
+ );
90
+ }
91
+ return handleAuth(event, {
92
+ url,
93
+ protectedRoutes,
94
+ loginPath,
95
+ allowedAlgorithms,
96
+ clockSkewMs,
97
+ audience,
98
+ allowedTokenTypes,
99
+ jwksTimeoutMs,
100
+ pathname
101
+ });
102
+ });
103
+ }
104
+ async function proxyRequest(event, authUrl, proxyPath, url, proxyTimeoutMs, onExchangeResponse) {
105
+ const suffix = url.pathname.slice(proxyPath.length);
106
+ const target = `${authUrl}${suffix}${url.search}`;
107
+ const method = event.node.req.method ?? "GET";
108
+ const hasBody = !["GET", "HEAD"].includes(method);
109
+ const rawBody = hasBody ? await readRawBody(event, false) : void 0;
110
+ const body = rawBody != null ? new Uint8Array(rawBody) : void 0;
111
+ const upstream = await fetch(target, {
112
+ method,
113
+ headers: buildUpstreamHeaders(event),
114
+ body,
115
+ redirect: "manual",
116
+ signal: AbortSignal.timeout(proxyTimeoutMs)
117
+ });
118
+ const responseHeaders = filterResponseHeaders(upstream.headers);
119
+ const setCookieHeaders = upstream.headers.getSetCookie?.() ?? [];
120
+ for (const cookie of setCookieHeaders) {
121
+ responseHeaders.append("set-cookie", cookie);
122
+ }
123
+ let response = new Response(upstream.body, {
124
+ status: upstream.status,
125
+ headers: responseHeaders
126
+ });
127
+ const isExchange = method === "POST" && suffix.startsWith("/sessions/exchange");
128
+ if (isExchange && onExchangeResponse) {
129
+ response = await onExchangeResponse(response);
130
+ }
131
+ event.node.res.statusCode = response.status;
132
+ for (const [key, value] of response.headers.entries()) {
133
+ if (key.toLowerCase() === "set-cookie") continue;
134
+ event.node.res.setHeader(key, value);
135
+ }
136
+ const finalCookies = response.headers.getSetCookie?.() ?? [];
137
+ for (const cookie of finalCookies) {
138
+ event.node.res.appendHeader("set-cookie", cookie);
139
+ }
140
+ return response.body;
141
+ }
142
+ async function handleAuth(event, opts) {
143
+ const {
144
+ url,
145
+ protectedRoutes,
146
+ loginPath,
147
+ allowedAlgorithms,
148
+ clockSkewMs,
149
+ audience,
150
+ allowedTokenTypes,
151
+ jwksTimeoutMs,
152
+ pathname
153
+ } = opts;
154
+ delete event.node.req.headers["x-nextgen-auth-token"];
155
+ const authHeader = getRequestHeader(event, "authorization");
156
+ const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
157
+ const cookieToken = getCookie(event, "__nextgen_session") ?? null;
158
+ const token = bearerToken ?? cookieToken;
159
+ const payload = token ? await verifyJwt(token, {
160
+ issuerUrl: url,
161
+ allowedAlgorithms,
162
+ clockSkewMs,
163
+ audience,
164
+ allowedTokenTypes,
165
+ jwksTimeoutMs
166
+ }) : null;
167
+ if (payload && token && payload.sub) {
168
+ event.context.nextgenAuth = {
169
+ isAuthenticated: true,
170
+ session: {
171
+ userId: payload.sub,
172
+ email: payload.email ?? null,
173
+ name: payload.name ?? null,
174
+ token
175
+ }
176
+ };
177
+ return;
178
+ }
179
+ event.context.nextgenAuth = { isAuthenticated: false, session: null };
180
+ for (const name of Object.keys(parseCookies(event))) {
181
+ if (name.startsWith("__nextgen")) {
182
+ deleteCookie(event, name);
183
+ }
184
+ }
185
+ if (matchesRoutes(pathname, protectedRoutes)) {
186
+ const loginUrl = new URL(loginPath, getRequestURL(event));
187
+ loginUrl.searchParams.set("next", pathname);
188
+ await sendRedirect(event, loginUrl.toString(), 302);
189
+ return;
190
+ }
191
+ }
192
+ function getAuth(event) {
193
+ return event.context.nextgenAuth ?? { isAuthenticated: false, session: null };
194
+ }
195
+
196
+ export {
197
+ createNextgenMiddleware,
198
+ getAuth
199
+ };
File without changes
@@ -0,0 +1,32 @@
1
+ export { ZitadelLogin, ZitadelLogout } from '@zitadel/components';
2
+ export { createNextgenMiddleware, getAuth } from './runtime/server/middleware.js';
3
+ import { ZitadelProject } from '@zitadel/api/config';
4
+ export { ClientAuthResult } from './runtime/types.js';
5
+ export { AuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/types';
6
+ import 'h3';
7
+
8
+ /**
9
+ * Returns the current Zitadel project handle.
10
+ *
11
+ * Reads from the global config set by `configureZitadel()` in the
12
+ * Nextgen Nuxt plugin. Pass the returned handle to web components
13
+ * via the `:project` prop for explicit data flow.
14
+ *
15
+ * ```vue
16
+ * <script setup lang="ts">
17
+ * import { useZitadelProject } from '@zitadel/sdk-nuxt';
18
+ *
19
+ * const project = useZitadelProject();
20
+ * </script>
21
+ *
22
+ * <template>
23
+ * <zitadel-login :project="project" post-sign-in-url="/admin" />
24
+ * </template>
25
+ * ```
26
+ *
27
+ * @returns The current {@link ZitadelProject}, or `null` if the plugin
28
+ * has not been configured (e.g. missing `projectId`).
29
+ */
30
+ declare function useZitadelProject(): ZitadelProject | null;
31
+
32
+ export { useZitadelProject };
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ import "./chunk-ZNXAFGLP.js";
2
+ import {
3
+ createNextgenMiddleware,
4
+ getAuth
5
+ } from "./chunk-J2P7YNGG.js";
6
+
7
+ // src/index.ts
8
+ import { ZitadelLogin, ZitadelLogout } from "@zitadel/components";
9
+
10
+ // src/runtime/composables/useZitadelProject.ts
11
+ import { getZitadelConfig } from "@zitadel/api/config";
12
+ function useZitadelProject() {
13
+ return getZitadelConfig();
14
+ }
15
+ export {
16
+ ZitadelLogin,
17
+ ZitadelLogout,
18
+ createNextgenMiddleware,
19
+ getAuth,
20
+ useZitadelProject
21
+ };
package/dist/module.js ADDED
@@ -0,0 +1,40 @@
1
+ // src/module.ts
2
+ import {
3
+ defineNuxtModule,
4
+ addPlugin,
5
+ addServerHandler,
6
+ addImportsDir,
7
+ createResolver
8
+ } from "@nuxt/kit";
9
+ var module_default = defineNuxtModule({
10
+ meta: {
11
+ name: "@zitadel/sdk-nuxt",
12
+ configKey: "nextgen"
13
+ },
14
+ defaults: {
15
+ url: process.env.ZITADEL_URL ?? "http://localhost:8080",
16
+ proxyPath: "/__nextgen",
17
+ protectedRoutes: [],
18
+ loginPath: "/login"
19
+ },
20
+ setup(options, nuxt) {
21
+ const { resolve } = createResolver(import.meta.url);
22
+ nuxt.options.runtimeConfig.nextgen = {
23
+ url: options.url ?? "http://localhost:4000",
24
+ loginPath: options.loginPath ?? "/login",
25
+ protectedRoutes: options.protectedRoutes ?? [],
26
+ jwtKey: options.jwtKey
27
+ };
28
+ nuxt.options.runtimeConfig.public.zitadelProxyPath = options.proxyPath ?? "/__nextgen";
29
+ nuxt.options.runtimeConfig.public.nextgenProxyPath = options.proxyPath ?? "/__nextgen";
30
+ addPlugin(resolve("./runtime/plugin"));
31
+ addServerHandler({
32
+ middleware: true,
33
+ handler: resolve("./runtime/server/handler")
34
+ });
35
+ addImportsDir(resolve("./runtime/composables"));
36
+ }
37
+ });
38
+ export {
39
+ module_default as default
40
+ };
@@ -0,0 +1,9 @@
1
+ // src/runtime/composables/useAuth.ts
2
+ import { useState } from "#imports";
3
+ var useAuth = () => useState("nextgen-auth", () => ({
4
+ isAuthenticated: false,
5
+ session: null
6
+ })).value;
7
+ export {
8
+ useAuth
9
+ };
@@ -0,0 +1,35 @@
1
+ // src/runtime/plugin.ts
2
+ import {
3
+ defineNuxtPlugin,
4
+ useRequestEvent,
5
+ useRuntimeConfig,
6
+ useState
7
+ } from "#imports";
8
+ import { configureZitadel } from "@zitadel/api/config";
9
+ var plugin_default = defineNuxtPlugin(() => {
10
+ const event = useRequestEvent();
11
+ const auth = event?.context.nextgenAuth ?? {
12
+ isAuthenticated: false,
13
+ session: null
14
+ };
15
+ const clientAuth = auth.isAuthenticated ? {
16
+ isAuthenticated: true,
17
+ session: {
18
+ userId: auth.session.userId,
19
+ email: auth.session.email,
20
+ name: auth.session.name
21
+ }
22
+ } : { isAuthenticated: false, session: null };
23
+ useState("nextgen-auth", () => clientAuth);
24
+ const runtimeConfig = useRuntimeConfig();
25
+ const publicConfig = runtimeConfig.public;
26
+ const proxyPath = publicConfig.zitadelProxyPath ?? publicConfig.nextgenProxyPath ?? publicConfig.nextgenApiBase ?? "/__nextgen";
27
+ const projectId = publicConfig.zitadelProjectId ?? "";
28
+ const url = runtimeConfig.nextgen?.url ?? runtimeConfig.nextgen?.issuerUrl ?? "http://localhost:4000";
29
+ if (proxyPath && projectId) {
30
+ configureZitadel({ proxyPath, projectId, url });
31
+ }
32
+ });
33
+ export {
34
+ plugin_default as default
35
+ };
@@ -0,0 +1,11 @@
1
+ import * as h3 from 'h3';
2
+
3
+ /**
4
+ * Default Nitro/H3 event handler registered by the `@zitadel/sdk-nuxt` module
5
+ * via {@link addServerHandler}. Reads middleware options from Nuxt runtime
6
+ * config (`nuxt.config.ts → nextgen`) so consumers do not need to create
7
+ * their own `server/middleware/auth.ts` when using the module.
8
+ */
9
+ declare const _default: h3.EventHandler<h3.EventHandlerRequest, any>;
10
+
11
+ export { _default as default };
@@ -0,0 +1,14 @@
1
+ import {
2
+ createNextgenMiddleware
3
+ } from "../../chunk-J2P7YNGG.js";
4
+
5
+ // src/runtime/server/handler.ts
6
+ var config = useRuntimeConfig();
7
+ var handler_default = createNextgenMiddleware({
8
+ url: config.nextgen?.url ?? config.nextgen?.issuerUrl ?? "http://localhost:4000",
9
+ loginPath: config.nextgen?.loginPath ?? "/login",
10
+ protectedRoutes: config.nextgen?.protectedRoutes ?? []
11
+ });
12
+ export {
13
+ handler_default as default
14
+ };
@@ -0,0 +1,49 @@
1
+ import { AuthResult, NextgenMiddlewareOptions } from '@zitadel/sdk-core/types';
2
+ import { EventHandler, H3Event } from 'h3';
3
+
4
+ declare module 'h3' {
5
+ interface H3EventContext {
6
+ nextgenAuth: AuthResult;
7
+ }
8
+ }
9
+ /**
10
+ * Creates an H3 event handler that handles proxying, JWT verification, and
11
+ * route protection in a single pass.
12
+ *
13
+ * Register it as a Nitro server middleware in `server/middleware/auth.ts`:
14
+ *
15
+ * ```ts
16
+ * import { createNextgenMiddleware } from "@zitadel/sdk-nuxt/server";
17
+ *
18
+ * export default createNextgenMiddleware({
19
+ * url: process.env.ZITADEL_URL,
20
+ * protectedRoutes: ["/admin*", "/dashboard*"],
21
+ * loginPath: "/login",
22
+ * });
23
+ * ```
24
+ *
25
+ * @param options - Middleware configuration options.
26
+ * @returns An H3 event handler suitable for use as a global server middleware.
27
+ */
28
+ declare function createNextgenMiddleware(options?: NextgenMiddlewareOptions): EventHandler;
29
+ /**
30
+ * Reads the auth state from a Nitro/H3 event context.
31
+ *
32
+ * Call this inside any server route or API handler after the middleware has run:
33
+ *
34
+ * ```ts
35
+ * import { getAuth } from "@zitadel/sdk-nuxt/server";
36
+ *
37
+ * export default defineEventHandler((event) => {
38
+ * const auth = getAuth(event);
39
+ * if (!auth.isAuthenticated) throw createError({ statusCode: 401 });
40
+ * return { userId: auth.session.userId };
41
+ * });
42
+ * ```
43
+ *
44
+ * @param event - The current H3 event.
45
+ * @returns The current {@link AuthResult}.
46
+ */
47
+ declare function getAuth(event: H3Event): AuthResult;
48
+
49
+ export { createNextgenMiddleware, getAuth };
@@ -0,0 +1,8 @@
1
+ import {
2
+ createNextgenMiddleware,
3
+ getAuth
4
+ } from "../../chunk-J2P7YNGG.js";
5
+ export {
6
+ createNextgenMiddleware,
7
+ getAuth
8
+ };
@@ -0,0 +1,37 @@
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 };
File without changes
@@ -0,0 +1,3 @@
1
+ export { createNextgenMiddleware, getAuth } from './runtime/server/middleware.js';
2
+ import '@zitadel/sdk-core/types';
3
+ import 'h3';
package/dist/server.js ADDED
@@ -0,0 +1,9 @@
1
+ import "./chunk-ZNXAFGLP.js";
2
+ import {
3
+ createNextgenMiddleware,
4
+ getAuth
5
+ } from "./chunk-J2P7YNGG.js";
6
+ export {
7
+ createNextgenMiddleware,
8
+ getAuth
9
+ };
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@zitadel/sdk-nuxt",
3
+ "version": "0.0.0",
4
+ "description": "Nuxt proxy middleware and helpers for Nextgen Auth",
5
+ "homepage": "https://github.com/zitadel/nextgen/tree/main/packages/sdk-nuxt#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/zitadel/nextgen/issues"
8
+ },
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/zitadel/nextgen.git",
13
+ "directory": "packages/sdk-nuxt"
14
+ },
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./module": {
22
+ "import": "./dist/module.js"
23
+ },
24
+ "./server": {
25
+ "types": "./dist/server.d.ts",
26
+ "import": "./dist/server.js"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "dependencies": {
36
+ "@zitadel/api": "0.0.0",
37
+ "@zitadel/components": "0.0.0",
38
+ "@zitadel/sdk-core": "0.0.0"
39
+ },
40
+ "peerDependencies": {
41
+ "h3": ">=1",
42
+ "nuxt": ">=4"
43
+ },
44
+ "devDependencies": {
45
+ "@eslint/js": "^9.0.0",
46
+ "@eslint/json": "^0.11.0",
47
+ "@eslint/markdown": "^6.0.0",
48
+ "@nuxt/eslint-plugin": "^0.7.0",
49
+ "eslint": "^9.0.0",
50
+ "eslint-config-prettier": "^10.0.0",
51
+ "eslint-import-resolver-typescript": "^3.7.0",
52
+ "eslint-plugin-import": "^2.31.0",
53
+ "eslint-plugin-perfectionist": "^4.0.0",
54
+ "eslint-plugin-prettier": "^5.0.0",
55
+ "h3": "^1.15.3",
56
+ "prettier": "^3.0.0",
57
+ "tsup": "^8.3.5",
58
+ "typescript": "^5.7.3",
59
+ "typescript-eslint": "^8.0.0",
60
+ "vitest": "^3.0.0"
61
+ },
62
+ "scripts": {
63
+ "build": "tsup src/index.ts src/server.ts src/runtime/types.ts src/runtime/server/middleware.ts src/runtime/server/handler.ts --format esm --dts --clean && tsup src/runtime/plugin.ts src/runtime/composables/useAuth.ts src/module.ts --format esm --no-clean --external @nuxt/kit --external '#imports'",
64
+ "dev": "tsup src/index.ts src/server.ts --format esm --dts --watch",
65
+ "typecheck": "tsc --noEmit",
66
+ "test": "vitest run --passWithNoTests",
67
+ "lint": "eslint ."
68
+ }
69
+ }