@zitadel/sdk-next 0.0.0 → 0.1.0-alpha.2
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/dist/auth.d.ts +7 -5
- package/dist/auth.js +2 -2
- package/dist/{chunk-UTJFJPDR.js → chunk-4KENHIG4.js} +51 -6
- package/dist/chunk-B7S6XMT3.js +41 -0
- package/dist/{chunk-5P5THDJF.js → chunk-OCZMYSFX.js} +1 -0
- package/dist/index.js +3 -3
- package/dist/middleware.js +2 -2
- package/dist/server.js +2 -2
- package/package.json +4 -4
- package/dist/chunk-EAUJMJ45.js +0 -34
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/auth.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { AuthResult } from '@zitadel/sdk-core/types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Reads the auth state in a React Server Component or Next.js Route Handler.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* - **JWT tokens** are decoded locally (no backend round-trip).
|
|
7
|
+
* - **Opaque encrypted tokens** have already been validated by the
|
|
8
|
+
* middleware via `GET /sessions/me`. If the `x-nextgen-auth-token`
|
|
9
|
+
* header is set, the session is authentic. Session details (email,
|
|
10
|
+
* name) are not available server-side for opaque tokens — use the
|
|
11
|
+
* `/__nextgen/sessions/me` proxy from a client component to fetch them.
|
|
10
12
|
*
|
|
11
13
|
* ```ts
|
|
12
14
|
* import { auth } from "@zitadel/sdk-next";
|
|
@@ -14,7 +16,7 @@ import { AuthResult } from '@zitadel/sdk-core/types';
|
|
|
14
16
|
* export default async function Page() {
|
|
15
17
|
* const session = await auth();
|
|
16
18
|
* if (!session.isAuthenticated) return <p>Not signed in</p>;
|
|
17
|
-
* return <p>Hello {session.session.
|
|
19
|
+
* return <p>Hello {session.session.userId}</p>;
|
|
18
20
|
* }
|
|
19
21
|
* ```
|
|
20
22
|
*
|
package/dist/auth.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
base64UrlDecode,
|
|
2
3
|
verifyJwt
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OCZMYSFX.js";
|
|
4
5
|
|
|
5
6
|
// src/middleware.ts
|
|
6
7
|
import {
|
|
@@ -68,6 +69,31 @@ async function nextgenMiddleware(req, options = {}) {
|
|
|
68
69
|
pathname
|
|
69
70
|
});
|
|
70
71
|
}
|
|
72
|
+
var DECODER = new TextDecoder();
|
|
73
|
+
function isJwtShaped(token) {
|
|
74
|
+
const parts = token.split(".");
|
|
75
|
+
if (parts.length < 3 || !parts[0]) return false;
|
|
76
|
+
try {
|
|
77
|
+
const header = JSON.parse(
|
|
78
|
+
DECODER.decode(base64UrlDecode(parts[0]))
|
|
79
|
+
);
|
|
80
|
+
return typeof header?.alg === "string" && !("enc" in header);
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function validateOpaqueSessionToken(token, issuerUrl, timeoutMs) {
|
|
86
|
+
try {
|
|
87
|
+
const res = await fetch(`${issuerUrl}/sessions/me`, {
|
|
88
|
+
method: "GET",
|
|
89
|
+
headers: { cookie: `__nextgen_session=${token}` },
|
|
90
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
91
|
+
});
|
|
92
|
+
return res.ok;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
71
97
|
async function proxyRequest(req, authUrl, proxyPath, proxyTimeoutMs, onExchangeResponse) {
|
|
72
98
|
const url = new URL(req.url);
|
|
73
99
|
const suffix = url.pathname.slice(proxyPath.length);
|
|
@@ -94,13 +120,20 @@ async function proxyRequest(req, authUrl, proxyPath, proxyTimeoutMs, onExchangeR
|
|
|
94
120
|
upstreamHeaders.set("x-forwarded-proto", url.protocol.replace(":", ""));
|
|
95
121
|
}
|
|
96
122
|
const hasBody = !["GET", "HEAD"].includes(req.method);
|
|
123
|
+
const isExchangeRequest = req.method === "POST" && suffix.startsWith("/sessions/exchange");
|
|
124
|
+
if (isExchangeRequest && !upstreamHeaders.has("authorization")) {
|
|
125
|
+
const projectId = url.searchParams.get("project_id");
|
|
126
|
+
if (projectId) {
|
|
127
|
+
upstreamHeaders.set("authorization", `Bearer sk_${projectId}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const bodyBuffer = hasBody ? await req.arrayBuffer() : void 0;
|
|
97
131
|
const upstream = await fetch(target, {
|
|
98
132
|
method: req.method,
|
|
99
133
|
headers: upstreamHeaders,
|
|
100
|
-
body:
|
|
134
|
+
body: bodyBuffer,
|
|
101
135
|
redirect: "manual",
|
|
102
|
-
signal: AbortSignal.timeout(proxyTimeoutMs)
|
|
103
|
-
...hasBody ? { duplex: "half" } : {}
|
|
136
|
+
signal: AbortSignal.timeout(proxyTimeoutMs)
|
|
104
137
|
});
|
|
105
138
|
const responseHeaders = filterResponseHeaders(upstream.headers);
|
|
106
139
|
const setCookies = upstream.headers.getSetCookie?.() ?? [];
|
|
@@ -111,8 +144,7 @@ async function proxyRequest(req, authUrl, proxyPath, proxyTimeoutMs, onExchangeR
|
|
|
111
144
|
status: upstream.status,
|
|
112
145
|
headers: responseHeaders
|
|
113
146
|
});
|
|
114
|
-
|
|
115
|
-
if (isExchange && onExchangeResponse) {
|
|
147
|
+
if (isExchangeRequest && onExchangeResponse) {
|
|
116
148
|
response = await onExchangeResponse(response);
|
|
117
149
|
}
|
|
118
150
|
return response;
|
|
@@ -145,6 +177,19 @@ async function handleAuth(req, opts) {
|
|
|
145
177
|
const tunnelled2 = tunnelHeaders(req, { "x-nextgen-auth-token": token });
|
|
146
178
|
return NextResponse.next({ request: { headers: tunnelled2 } });
|
|
147
179
|
}
|
|
180
|
+
if (!payload && cookieToken && !isJwtShaped(cookieToken)) {
|
|
181
|
+
const isValid = await validateOpaqueSessionToken(
|
|
182
|
+
cookieToken,
|
|
183
|
+
url,
|
|
184
|
+
jwksTimeoutMs ?? 5e3
|
|
185
|
+
);
|
|
186
|
+
if (isValid) {
|
|
187
|
+
const tunnelled2 = tunnelHeaders(req, {
|
|
188
|
+
"x-nextgen-auth-token": cookieToken
|
|
189
|
+
});
|
|
190
|
+
return NextResponse.next({ request: { headers: tunnelled2 } });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
148
193
|
const tunnelled = tunnelHeaders(req, { "x-nextgen-auth-token": "" });
|
|
149
194
|
const staleNextgenCookies = req.cookies.getAll().filter((c) => c.name.startsWith("__nextgen"));
|
|
150
195
|
if (matchesRoutes(pathname, protectedRoutes)) {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
decodeJwt
|
|
3
|
+
} from "./chunk-OCZMYSFX.js";
|
|
4
|
+
|
|
5
|
+
// src/auth.ts
|
|
6
|
+
import { headers } from "next/headers";
|
|
7
|
+
async function auth() {
|
|
8
|
+
const headerStore = await headers();
|
|
9
|
+
const token = headerStore.get("x-nextgen-auth-token");
|
|
10
|
+
if (!token) {
|
|
11
|
+
return { isAuthenticated: false, session: null };
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const { payload } = decodeJwt(token);
|
|
15
|
+
if (payload.sub) {
|
|
16
|
+
return {
|
|
17
|
+
isAuthenticated: true,
|
|
18
|
+
session: {
|
|
19
|
+
userId: payload.sub,
|
|
20
|
+
email: payload.email ?? null,
|
|
21
|
+
name: payload.name ?? null,
|
|
22
|
+
token
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
isAuthenticated: true,
|
|
30
|
+
session: {
|
|
31
|
+
userId: "unknown",
|
|
32
|
+
email: null,
|
|
33
|
+
name: null,
|
|
34
|
+
token
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
auth
|
|
41
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createProxy,
|
|
3
3
|
nextgenMiddleware
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4KENHIG4.js";
|
|
5
5
|
import {
|
|
6
6
|
auth
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-B7S6XMT3.js";
|
|
8
|
+
import "./chunk-OCZMYSFX.js";
|
|
9
9
|
import "./chunk-6F4PWJZI.js";
|
|
10
10
|
import {
|
|
11
11
|
useAuth
|
package/dist/middleware.js
CHANGED
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zitadel/sdk-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Next.js helpers and mock auth UI for Zitadel",
|
|
5
5
|
"homepage": "https://github.com/zitadel/nextgen/tree/main/packages/sdk-next#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"server-only": "^0.0.1",
|
|
42
|
-
"@zitadel/api": "0.0.
|
|
43
|
-
"@zitadel/
|
|
44
|
-
"@zitadel/
|
|
42
|
+
"@zitadel/api": "0.1.0-alpha.2",
|
|
43
|
+
"@zitadel/components": "0.1.0-alpha.2",
|
|
44
|
+
"@zitadel/sdk-core": "0.1.0-alpha.2"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"next": ">=14",
|
package/dist/chunk-EAUJMJ45.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
decodeJwt
|
|
3
|
-
} from "./chunk-5P5THDJF.js";
|
|
4
|
-
|
|
5
|
-
// src/auth.ts
|
|
6
|
-
import { headers } from "next/headers";
|
|
7
|
-
async function auth() {
|
|
8
|
-
try {
|
|
9
|
-
const headerStore = await headers();
|
|
10
|
-
const token = headerStore.get("x-nextgen-auth-token");
|
|
11
|
-
if (!token) {
|
|
12
|
-
return { isAuthenticated: false, session: null };
|
|
13
|
-
}
|
|
14
|
-
const { payload } = decodeJwt(token);
|
|
15
|
-
if (!payload.sub) {
|
|
16
|
-
return { isAuthenticated: false, session: null };
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
isAuthenticated: true,
|
|
20
|
-
session: {
|
|
21
|
-
userId: payload.sub,
|
|
22
|
-
email: payload.email ?? null,
|
|
23
|
-
name: payload.name ?? null,
|
|
24
|
-
token
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
} catch {
|
|
28
|
-
return { isAuthenticated: false, session: null };
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export {
|
|
33
|
-
auth
|
|
34
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"fileNames":[],"fileInfos":[],"root":[],"options":{"composite":true,"declarationMap":true,"emitDeclarationOnly":true,"importHelpers":true,"module":99,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noUncheckedIndexedAccess":true,"noUnusedLocals":true,"skipLibCheck":true,"strict":true,"target":9,"tsBuildInfoFile":"./tsconfig.tsbuildinfo"},"version":"5.9.3"}
|