@pontive/pontkit-server 1.1.0 → 1.2.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/dist/browser-mode.d.ts +23 -0
- package/dist/config.d.ts +26 -5
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +240 -185
- package/dist/index.js.map +1 -1
- package/dist/oidc.d.ts +6 -3
- package/dist/server-auth.d.ts +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,39 +1,6 @@
|
|
|
1
|
-
import { jwtVerify as
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
const e = ["issuer", "clientId", "sessionSecret"];
|
|
5
|
-
for (const r of e)
|
|
6
|
-
if (!t[r]) throw new Error(`@pontive/pontkit-server: ${r} is required`);
|
|
7
|
-
if (t.sessionSecret.length < 32)
|
|
8
|
-
throw new Error("@pontive/pontkit-server: sessionSecret must be at least 32 characters");
|
|
9
|
-
if (t.baseUrl)
|
|
10
|
-
try {
|
|
11
|
-
new URL(t.baseUrl);
|
|
12
|
-
} catch {
|
|
13
|
-
throw new Error(`@pontive/pontkit-server: baseUrl "${t.baseUrl}" is not an absolute URL`);
|
|
14
|
-
}
|
|
15
|
-
return {
|
|
16
|
-
issuer: t.issuer.replace(/\/+$/, ""),
|
|
17
|
-
clientId: t.clientId,
|
|
18
|
-
clientSecret: t.clientSecret || void 0,
|
|
19
|
-
sessionSecret: t.sessionSecret,
|
|
20
|
-
baseUrl: t.baseUrl ? new URL(t.baseUrl).origin : void 0,
|
|
21
|
-
scopes: t.scopes ?? "openid email profile offline_access",
|
|
22
|
-
basePath: (t.basePath ?? "/api/auth").replace(/\/+$/, ""),
|
|
23
|
-
redirectUri: t.redirectUri,
|
|
24
|
-
signInPath: t.signInPath ?? "/login",
|
|
25
|
-
afterSignInPath: t.afterSignInPath ?? "/",
|
|
26
|
-
prompt: t.prompt,
|
|
27
|
-
cookieName: t.cookieName ?? "pontive_session",
|
|
28
|
-
secureCookies: t.secureCookies,
|
|
29
|
-
sessionMaxAgeSeconds: t.sessionMaxAgeSeconds ?? q,
|
|
30
|
-
refreshSkewSeconds: t.refreshSkewSeconds ?? 60,
|
|
31
|
-
fetch: t.fetch ?? ((...r) => fetch(...r)),
|
|
32
|
-
logger: t.logger ?? console
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
const P = 3500, $ = 16;
|
|
36
|
-
function x(t) {
|
|
1
|
+
import { jwtVerify as I, createLocalJWKSet as Z, jwtDecrypt as Q, EncryptJWT as q } from "jose";
|
|
2
|
+
const b = 3500, T = 16;
|
|
3
|
+
function S(t) {
|
|
37
4
|
const e = /* @__PURE__ */ new Map();
|
|
38
5
|
if (!t) return e;
|
|
39
6
|
for (const r of t.split(";")) {
|
|
@@ -44,49 +11,49 @@ function x(t) {
|
|
|
44
11
|
}
|
|
45
12
|
return e;
|
|
46
13
|
}
|
|
47
|
-
function
|
|
14
|
+
function $(t) {
|
|
48
15
|
return [...t].map(([e, r]) => `${e}=${r}`).join("; ");
|
|
49
16
|
}
|
|
50
|
-
function
|
|
17
|
+
function C(t, e, r) {
|
|
51
18
|
const n = [`${t}=${e}`, "Path=/", "HttpOnly", "SameSite=Lax", `Max-Age=${r.maxAge}`];
|
|
52
19
|
return r.secure && n.push("Secure"), n.join("; ");
|
|
53
20
|
}
|
|
54
|
-
function
|
|
21
|
+
function U(t, e) {
|
|
55
22
|
return e === 0 ? t : `${t}.${e}`;
|
|
56
23
|
}
|
|
57
|
-
function
|
|
24
|
+
function ee(t, e) {
|
|
58
25
|
const r = t.get(e);
|
|
59
26
|
if (r === void 0) return null;
|
|
60
27
|
let n = r;
|
|
61
|
-
for (let s = 1; s <
|
|
62
|
-
const a = t.get(
|
|
28
|
+
for (let s = 1; s < T; s++) {
|
|
29
|
+
const a = t.get(U(e, s));
|
|
63
30
|
if (a === void 0) break;
|
|
64
31
|
n += a;
|
|
65
32
|
}
|
|
66
33
|
return n;
|
|
67
34
|
}
|
|
68
|
-
function
|
|
69
|
-
const s = [], a = Math.max(1, Math.ceil(r.length /
|
|
70
|
-
for (let
|
|
71
|
-
const d = r.slice(
|
|
72
|
-
t.set(
|
|
35
|
+
function te(t, e, r, n) {
|
|
36
|
+
const s = [], a = Math.max(1, Math.ceil(r.length / b));
|
|
37
|
+
for (let c = 0; c < a; c++) {
|
|
38
|
+
const d = r.slice(c * b, (c + 1) * b);
|
|
39
|
+
t.set(U(e, c), d), s.push(C(U(e, c), d, n));
|
|
73
40
|
}
|
|
74
|
-
for (let
|
|
75
|
-
const d =
|
|
41
|
+
for (let c = a; c < T; c++) {
|
|
42
|
+
const d = U(e, c);
|
|
76
43
|
if (!t.has(d)) break;
|
|
77
|
-
t.delete(d), s.push(
|
|
44
|
+
t.delete(d), s.push(C(d, "", { ...n, maxAge: 0 }));
|
|
78
45
|
}
|
|
79
46
|
return s;
|
|
80
47
|
}
|
|
81
48
|
function R(t, e, r) {
|
|
82
49
|
const n = [];
|
|
83
|
-
for (let s = 0; s <
|
|
84
|
-
const a =
|
|
50
|
+
for (let s = 0; s < T; s++) {
|
|
51
|
+
const a = U(e, s);
|
|
85
52
|
if (!t.has(a)) {
|
|
86
53
|
if (s > 0) break;
|
|
87
54
|
continue;
|
|
88
55
|
}
|
|
89
|
-
t.delete(a), n.push(
|
|
56
|
+
t.delete(a), n.push(C(a, "", { maxAge: 0, secure: r }));
|
|
90
57
|
}
|
|
91
58
|
return n;
|
|
92
59
|
}
|
|
@@ -97,111 +64,193 @@ class W extends Error {
|
|
|
97
64
|
status;
|
|
98
65
|
code;
|
|
99
66
|
}
|
|
100
|
-
const
|
|
101
|
-
function
|
|
67
|
+
const re = 600 * 1e3, A = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new Map();
|
|
68
|
+
function ne(t) {
|
|
102
69
|
return t.replace(/\/+$/, "");
|
|
103
70
|
}
|
|
104
|
-
function
|
|
105
|
-
const r =
|
|
106
|
-
let n =
|
|
71
|
+
function P(t, e) {
|
|
72
|
+
const r = ne(t);
|
|
73
|
+
let n = A.get(r);
|
|
107
74
|
return n || (n = e(`${r}/.well-known/openid-configuration`).then(async (s) => {
|
|
108
75
|
if (!s.ok) throw new Error(`OIDC discovery failed for ${r}: ${s.status}`);
|
|
109
76
|
return await s.json();
|
|
110
77
|
}).catch((s) => {
|
|
111
|
-
throw
|
|
112
|
-
}),
|
|
78
|
+
throw A.delete(r), s;
|
|
79
|
+
}), A.set(r, n)), n;
|
|
113
80
|
}
|
|
114
81
|
async function M(t, e, r) {
|
|
115
82
|
const n = L.get(t);
|
|
116
|
-
if (n && !r && Date.now() - n.at <
|
|
83
|
+
if (n && !r && Date.now() - n.at < re) return n.set;
|
|
117
84
|
const s = await e(t);
|
|
118
85
|
if (!s.ok) throw new Error(`JWKS fetch failed for ${t}: ${s.status}`);
|
|
119
|
-
const a =
|
|
86
|
+
const a = Z(await s.json());
|
|
120
87
|
return L.set(t, { at: Date.now(), set: a }), a;
|
|
121
88
|
}
|
|
122
|
-
function
|
|
89
|
+
function K(t) {
|
|
123
90
|
let e = "";
|
|
124
91
|
for (const r of t) e += String.fromCharCode(r);
|
|
125
92
|
return btoa(e).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
126
93
|
}
|
|
127
|
-
function
|
|
128
|
-
return
|
|
94
|
+
function v() {
|
|
95
|
+
return K(crypto.getRandomValues(new Uint8Array(32)));
|
|
129
96
|
}
|
|
130
|
-
async function
|
|
97
|
+
async function se(t) {
|
|
131
98
|
const e = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(t));
|
|
132
|
-
return
|
|
99
|
+
return K(new Uint8Array(e));
|
|
133
100
|
}
|
|
134
|
-
async function
|
|
101
|
+
async function oe(t) {
|
|
135
102
|
return [...new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(t)))].map((r) => r.toString(16).padStart(2, "0")).join("");
|
|
136
103
|
}
|
|
137
|
-
async function
|
|
138
|
-
const n = await
|
|
104
|
+
async function ie(t, e, r) {
|
|
105
|
+
const n = await P(t.issuer, e), s = new URL(n.authorization_endpoint);
|
|
139
106
|
return s.searchParams.set("response_type", "code"), s.searchParams.set("client_id", t.clientId), s.searchParams.set("redirect_uri", r.redirectUri), s.searchParams.set("scope", r.scopes), s.searchParams.set("state", r.state), s.searchParams.set("nonce", r.nonce), s.searchParams.set("code_challenge", r.codeChallenge), s.searchParams.set("code_challenge_method", "S256"), r.prompt && s.searchParams.set("prompt", r.prompt), s.toString();
|
|
140
107
|
}
|
|
141
|
-
async function
|
|
142
|
-
const n = await
|
|
108
|
+
async function F(t, e, r) {
|
|
109
|
+
const n = await P(t.issuer, e), s = new URLSearchParams(r);
|
|
143
110
|
s.set("client_id", t.clientId);
|
|
144
111
|
const a = { "content-type": "application/x-www-form-urlencoded" };
|
|
145
112
|
if (t.clientSecret) {
|
|
146
113
|
const d = `${encodeURIComponent(t.clientId)}:${encodeURIComponent(t.clientSecret)}`;
|
|
147
114
|
a.authorization = `Basic ${btoa(d)}`;
|
|
148
115
|
}
|
|
149
|
-
const
|
|
150
|
-
if (!
|
|
151
|
-
let d = "unknown_error",
|
|
116
|
+
const c = await e(n.token_endpoint, { method: "POST", headers: a, body: s });
|
|
117
|
+
if (!c.ok) {
|
|
118
|
+
let d = "unknown_error", h = "";
|
|
152
119
|
try {
|
|
153
|
-
const
|
|
154
|
-
d =
|
|
120
|
+
const _ = await c.json();
|
|
121
|
+
d = _.error ?? d, h = _.error_description ?? "";
|
|
155
122
|
} catch {
|
|
156
123
|
}
|
|
157
|
-
throw new W(
|
|
124
|
+
throw new W(c.status, d, h);
|
|
158
125
|
}
|
|
159
|
-
return await
|
|
126
|
+
return await c.json();
|
|
160
127
|
}
|
|
161
|
-
function
|
|
162
|
-
return
|
|
128
|
+
function ae(t, e, r) {
|
|
129
|
+
return F(t, e, {
|
|
163
130
|
grant_type: "authorization_code",
|
|
164
131
|
code: r.code,
|
|
165
132
|
code_verifier: r.codeVerifier,
|
|
166
133
|
redirect_uri: r.redirectUri
|
|
167
134
|
});
|
|
168
135
|
}
|
|
169
|
-
function
|
|
170
|
-
return
|
|
136
|
+
function ce(t, e, r) {
|
|
137
|
+
return F(t, e, { grant_type: "refresh_token", refresh_token: r });
|
|
171
138
|
}
|
|
172
|
-
async function
|
|
173
|
-
const
|
|
174
|
-
let u;
|
|
139
|
+
async function V(t, e, r) {
|
|
140
|
+
const n = await P(t.issuer, e), s = { issuer: n.issuer, audience: t.clientId };
|
|
175
141
|
try {
|
|
176
|
-
|
|
177
|
-
} catch (
|
|
178
|
-
if (
|
|
179
|
-
|
|
142
|
+
return (await I(r, await M(n.jwks_uri, e, !1), s)).payload;
|
|
143
|
+
} catch (a) {
|
|
144
|
+
if (a.code !== "ERR_JWKS_NO_MATCHING_KEY") throw a;
|
|
145
|
+
return (await I(r, await M(n.jwks_uri, e, !0), s)).payload;
|
|
180
146
|
}
|
|
181
|
-
if (u.payload.nonce !== n) throw new Error("id_token nonce does not match the sign-in request");
|
|
182
|
-
return u.payload;
|
|
183
147
|
}
|
|
184
|
-
async function
|
|
185
|
-
const
|
|
148
|
+
async function ue(t, e, r, n) {
|
|
149
|
+
const s = await V(t, e, r);
|
|
150
|
+
if (s.nonce !== n) throw new Error("id_token nonce does not match the sign-in request");
|
|
151
|
+
return s;
|
|
152
|
+
}
|
|
153
|
+
async function de(t, e, r) {
|
|
154
|
+
const n = await P(t.issuer, e);
|
|
186
155
|
if (!n.end_session_endpoint) return null;
|
|
187
156
|
const s = new URL(n.end_session_endpoint);
|
|
188
157
|
return s.searchParams.set("client_id", t.clientId), s.searchParams.set("post_logout_redirect_uri", r.postLogoutRedirectUri), r.sessionId && s.searchParams.set("logout_hint", r.sessionId), s.toString();
|
|
189
158
|
}
|
|
190
|
-
const he =
|
|
191
|
-
|
|
192
|
-
|
|
159
|
+
const le = "__Host-pontive_access", he = "__Secure-pontive_session_state";
|
|
160
|
+
function fe(t) {
|
|
161
|
+
const e = (r) => typeof t[r] == "string" ? t[r] : void 0;
|
|
162
|
+
return {
|
|
163
|
+
id: t.sub ?? "",
|
|
164
|
+
email: e("email"),
|
|
165
|
+
name: e("name") ?? e("email"),
|
|
166
|
+
username: e("preferred_username"),
|
|
167
|
+
picture: e("picture"),
|
|
168
|
+
emailVerified: t.email_verified === !0
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function we(t) {
|
|
172
|
+
const e = { issuer: t.issuer, clientId: t.clientId };
|
|
173
|
+
async function r(n) {
|
|
174
|
+
const s = S(n).get(le);
|
|
175
|
+
if (!s) return null;
|
|
176
|
+
let a;
|
|
177
|
+
try {
|
|
178
|
+
a = await V(e, t.fetch, s);
|
|
179
|
+
} catch (c) {
|
|
180
|
+
return c.code !== "ERR_JWT_EXPIRED" && t.logger.warn("[pontive] access token cookie refused:", c instanceof Error ? c.message : String(c)), null;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
user: fe(a),
|
|
184
|
+
accessToken: s,
|
|
185
|
+
expiresAt: (a.exp ?? 0) * 1e3,
|
|
186
|
+
sessionId: typeof a.sid == "string" ? a.sid : void 0
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
// Sign-in and sign-out belong to the browser SDK's widgets in this mode.
|
|
191
|
+
async handle() {
|
|
192
|
+
return null;
|
|
193
|
+
},
|
|
194
|
+
getSession: r,
|
|
195
|
+
async refresh(n) {
|
|
196
|
+
const s = n.headers.get("cookie"), a = await r(s), c = { session: a, setCookies: [], cookieHeader: s ?? "" };
|
|
197
|
+
if (a || !S(s).has(he)) return c;
|
|
198
|
+
const d = new URL(n.url), h = new URL(`${t.authPath}/oauth2/session`, d.origin);
|
|
199
|
+
return h.searchParams.set("client_id", t.clientId), h.searchParams.set("return_to", d.pathname + d.search), { ...c, handshake: h.pathname + h.search };
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const pe = 10080 * 60;
|
|
204
|
+
function ge(t) {
|
|
205
|
+
const e = t.clientSecret ? "server" : "browser", r = ["issuer", "clientId"];
|
|
206
|
+
e === "server" && r.push("sessionSecret");
|
|
207
|
+
for (const n of r)
|
|
208
|
+
if (!t[n]) throw new Error(`@pontive/pontkit-server: ${n} is required`);
|
|
209
|
+
if (e === "server" && t.sessionSecret.length < 32)
|
|
210
|
+
throw new Error("@pontive/pontkit-server: sessionSecret must be at least 32 characters");
|
|
211
|
+
if (t.baseUrl)
|
|
212
|
+
try {
|
|
213
|
+
new URL(t.baseUrl);
|
|
214
|
+
} catch {
|
|
215
|
+
throw new Error(`@pontive/pontkit-server: baseUrl "${t.baseUrl}" is not an absolute URL`);
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
mode: e,
|
|
219
|
+
authPath: (t.authPath ?? "/__auth").replace(/\/+$/, ""),
|
|
220
|
+
issuer: t.issuer.replace(/\/+$/, ""),
|
|
221
|
+
clientId: t.clientId,
|
|
222
|
+
clientSecret: t.clientSecret || void 0,
|
|
223
|
+
sessionSecret: t.sessionSecret ?? "",
|
|
224
|
+
baseUrl: t.baseUrl ? new URL(t.baseUrl).origin : void 0,
|
|
225
|
+
scopes: t.scopes ?? "openid email profile offline_access",
|
|
226
|
+
basePath: (t.basePath ?? "/api/auth").replace(/\/+$/, ""),
|
|
227
|
+
redirectUri: t.redirectUri,
|
|
228
|
+
signInPath: t.signInPath ?? "/login",
|
|
229
|
+
afterSignInPath: t.afterSignInPath ?? "/",
|
|
230
|
+
prompt: t.prompt,
|
|
231
|
+
cookieName: t.cookieName ?? "pontive_session",
|
|
232
|
+
secureCookies: t.secureCookies,
|
|
233
|
+
sessionMaxAgeSeconds: t.sessionMaxAgeSeconds ?? pe,
|
|
234
|
+
refreshSkewSeconds: t.refreshSkewSeconds ?? 60,
|
|
235
|
+
fetch: t.fetch ?? ((...n) => fetch(...n)),
|
|
236
|
+
logger: t.logger ?? console
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const ke = 3e4;
|
|
240
|
+
class me {
|
|
241
|
+
constructor(e = ke) {
|
|
193
242
|
this.recentMs = e;
|
|
194
243
|
}
|
|
195
244
|
recentMs;
|
|
196
245
|
inFlight = /* @__PURE__ */ new Map();
|
|
197
246
|
recent = /* @__PURE__ */ new Map();
|
|
198
247
|
async run(e, r) {
|
|
199
|
-
const n = await
|
|
248
|
+
const n = await oe(e);
|
|
200
249
|
this.sweep();
|
|
201
250
|
const s = this.recent.get(n);
|
|
202
251
|
if (s) return s.result;
|
|
203
252
|
let a = this.inFlight.get(n);
|
|
204
|
-
return a || (a = r().then((
|
|
253
|
+
return a || (a = r().then((c) => (this.recent.set(n, { at: Date.now(), result: c }), c)).finally(() => this.inFlight.delete(n)), this.inFlight.set(n, a)), a;
|
|
205
254
|
}
|
|
206
255
|
sweep() {
|
|
207
256
|
const e = Date.now() - this.recentMs;
|
|
@@ -210,23 +259,23 @@ class fe {
|
|
|
210
259
|
}
|
|
211
260
|
}
|
|
212
261
|
const N = /* @__PURE__ */ new Map();
|
|
213
|
-
function
|
|
262
|
+
function J(t) {
|
|
214
263
|
let e = N.get(t);
|
|
215
264
|
return e || (e = crypto.subtle.digest("SHA-256", new TextEncoder().encode(t)).then((r) => new Uint8Array(r)), N.set(t, e)), e;
|
|
216
265
|
}
|
|
217
|
-
async function
|
|
218
|
-
return new
|
|
266
|
+
async function H(t, e, r) {
|
|
267
|
+
return new q(t).setProtectedHeader({ alg: "dir", enc: "A256GCM" }).setIssuedAt().setExpirationTime(`${r}s`).encrypt(await J(e));
|
|
219
268
|
}
|
|
220
269
|
async function D(t, e) {
|
|
221
270
|
try {
|
|
222
|
-
const { payload: r } = await
|
|
271
|
+
const { payload: r } = await Q(t, await J(e));
|
|
223
272
|
return r;
|
|
224
273
|
} catch {
|
|
225
274
|
return null;
|
|
226
275
|
}
|
|
227
276
|
}
|
|
228
|
-
const
|
|
229
|
-
function
|
|
277
|
+
const Se = 900, O = 600;
|
|
278
|
+
function _e(t, e) {
|
|
230
279
|
return t && t.startsWith("/") && !t.startsWith("//") && !t.startsWith("/\\") ? t : e;
|
|
231
280
|
}
|
|
232
281
|
function m(t, e = []) {
|
|
@@ -234,7 +283,7 @@ function m(t, e = []) {
|
|
|
234
283
|
for (const n of e) r.append("set-cookie", n);
|
|
235
284
|
return new Response(null, { status: 302, headers: r });
|
|
236
285
|
}
|
|
237
|
-
function
|
|
286
|
+
function E(t, e) {
|
|
238
287
|
if (t.baseUrl) return t.baseUrl;
|
|
239
288
|
const r = e.headers.get("x-forwarded-host")?.split(",")[0]?.trim() || e.headers.get("host")?.trim();
|
|
240
289
|
if (r) {
|
|
@@ -246,7 +295,7 @@ function C(t, e) {
|
|
|
246
295
|
}
|
|
247
296
|
return new URL(e.url).origin;
|
|
248
297
|
}
|
|
249
|
-
function
|
|
298
|
+
function ye(t) {
|
|
250
299
|
const e = (n) => typeof t[n] == "string" ? t[n] : void 0, r = e("name") ?? ([e("given_name"), e("family_name")].filter(Boolean).join(" ") || void 0) ?? e("email");
|
|
251
300
|
return {
|
|
252
301
|
id: t.sub ?? "",
|
|
@@ -257,92 +306,94 @@ function ge(t) {
|
|
|
257
306
|
emailVerified: t.email_verified === !0
|
|
258
307
|
};
|
|
259
308
|
}
|
|
260
|
-
function
|
|
261
|
-
return Date.now() + (t.expires_in ??
|
|
309
|
+
function j(t) {
|
|
310
|
+
return Date.now() + (t.expires_in ?? Se) * 1e3;
|
|
262
311
|
}
|
|
263
|
-
function
|
|
264
|
-
const e =
|
|
265
|
-
|
|
266
|
-
|
|
312
|
+
function Ce(t) {
|
|
313
|
+
const e = ge(t);
|
|
314
|
+
if (e.mode === "browser") return we(e);
|
|
315
|
+
const r = { issuer: e.issuer, clientId: e.clientId, clientSecret: e.clientSecret }, n = `${e.cookieName}_tx`, s = new me(), a = (o) => e.secureCookies ?? E(e, o).startsWith("https:"), c = (o) => e.redirectUri ?? `${E(e, o)}${e.basePath}/callback`, d = (o, i) => {
|
|
316
|
+
const u = new URL(e.signInPath, E(e, o));
|
|
317
|
+
return i && u.searchParams.set("error", i), u.toString();
|
|
267
318
|
};
|
|
268
|
-
async function
|
|
269
|
-
const i =
|
|
319
|
+
async function h(o) {
|
|
320
|
+
const i = ee(o, e.cookieName);
|
|
270
321
|
if (i === null) return null;
|
|
271
|
-
const
|
|
272
|
-
return
|
|
322
|
+
const u = await D(i, e.sessionSecret);
|
|
323
|
+
return u || e.logger.warn("[pontive] session cookie could not be read (sealed with another secret, or truncated)"), u;
|
|
273
324
|
}
|
|
274
|
-
async function
|
|
275
|
-
const l = await
|
|
276
|
-
return
|
|
325
|
+
async function _(o, i, u) {
|
|
326
|
+
const l = await H({ ...i }, e.sessionSecret, e.sessionMaxAgeSeconds);
|
|
327
|
+
return te(o, e.cookieName, l, { maxAge: e.sessionMaxAgeSeconds, secure: a(u) });
|
|
277
328
|
}
|
|
278
|
-
function
|
|
279
|
-
const { refreshToken: i, ...
|
|
280
|
-
return
|
|
329
|
+
function y(o) {
|
|
330
|
+
const { refreshToken: i, ...u } = o;
|
|
331
|
+
return u;
|
|
281
332
|
}
|
|
282
333
|
async function G(o) {
|
|
283
|
-
const i = new URL(o.url),
|
|
284
|
-
state:
|
|
285
|
-
verifier:
|
|
286
|
-
nonce:
|
|
287
|
-
returnTo:
|
|
288
|
-
}, l = await
|
|
289
|
-
redirectUri:
|
|
334
|
+
const i = new URL(o.url), u = {
|
|
335
|
+
state: v(),
|
|
336
|
+
verifier: v(),
|
|
337
|
+
nonce: v(),
|
|
338
|
+
returnTo: _e(i.searchParams.get("returnTo") ?? i.searchParams.get("next"), e.afterSignInPath)
|
|
339
|
+
}, l = await ie(r, e.fetch, {
|
|
340
|
+
redirectUri: c(o),
|
|
290
341
|
scopes: e.scopes,
|
|
291
|
-
state:
|
|
292
|
-
nonce:
|
|
293
|
-
codeChallenge: await
|
|
342
|
+
state: u.state,
|
|
343
|
+
nonce: u.nonce,
|
|
344
|
+
codeChallenge: await se(u.verifier),
|
|
294
345
|
prompt: e.prompt
|
|
295
|
-
}),
|
|
296
|
-
return m(l, [
|
|
346
|
+
}), f = await H({ ...u }, e.sessionSecret, O);
|
|
347
|
+
return m(l, [C(n, f, { maxAge: O, secure: a(o) })]);
|
|
297
348
|
}
|
|
298
349
|
async function z(o) {
|
|
299
|
-
const i = new URL(o.url),
|
|
300
|
-
if (
|
|
301
|
-
const
|
|
302
|
-
if (!
|
|
350
|
+
const i = new URL(o.url), u = S(o.headers.get("cookie")), l = [C(n, "", { maxAge: 0, secure: a(o) })], f = i.searchParams.get("error");
|
|
351
|
+
if (f) return m(d(o, f), l);
|
|
352
|
+
const w = u.get(n), k = w ? await D(w, e.sessionSecret) : null, p = i.searchParams.get("code");
|
|
353
|
+
if (!k || !p || i.searchParams.get("state") !== k.state)
|
|
303
354
|
return m(d(o, "invalid_state"), l);
|
|
304
355
|
try {
|
|
305
|
-
const
|
|
306
|
-
code:
|
|
307
|
-
codeVerifier:
|
|
308
|
-
redirectUri:
|
|
356
|
+
const g = await ae(r, e.fetch, {
|
|
357
|
+
code: p,
|
|
358
|
+
codeVerifier: k.verifier,
|
|
359
|
+
redirectUri: c(o)
|
|
309
360
|
});
|
|
310
|
-
if (!
|
|
311
|
-
const
|
|
312
|
-
user:
|
|
313
|
-
accessToken:
|
|
314
|
-
refreshToken:
|
|
315
|
-
expiresAt:
|
|
316
|
-
sessionId: typeof
|
|
361
|
+
if (!g.id_token) throw new Error("the token response carried no id_token; is the openid scope requested?");
|
|
362
|
+
const x = await ue(r, e.fetch, g.id_token, k.nonce), Y = {
|
|
363
|
+
user: ye(x),
|
|
364
|
+
accessToken: g.access_token,
|
|
365
|
+
refreshToken: g.refresh_token,
|
|
366
|
+
expiresAt: j(g),
|
|
367
|
+
sessionId: typeof x.sid == "string" ? x.sid : void 0
|
|
317
368
|
};
|
|
318
|
-
l.push(...await
|
|
319
|
-
} catch (
|
|
320
|
-
return e.logger.warn("[pontive] sign-in failed:",
|
|
369
|
+
l.push(...await _(u, Y, o));
|
|
370
|
+
} catch (g) {
|
|
371
|
+
return e.logger.warn("[pontive] sign-in failed:", g instanceof Error ? g.message : String(g)), m(d(o, "exchange_failed"), l);
|
|
321
372
|
}
|
|
322
|
-
return m(new URL(
|
|
373
|
+
return m(new URL(k.returnTo, E(e, o)).toString(), l);
|
|
323
374
|
}
|
|
324
|
-
async function
|
|
325
|
-
const i =
|
|
326
|
-
let
|
|
375
|
+
async function B(o) {
|
|
376
|
+
const i = S(o.headers.get("cookie")), u = await h(i), l = R(i, e.cookieName, a(o));
|
|
377
|
+
let f = d(o);
|
|
327
378
|
try {
|
|
328
|
-
|
|
379
|
+
f = await de(r, e.fetch, {
|
|
329
380
|
postLogoutRedirectUri: d(o),
|
|
330
|
-
sessionId:
|
|
331
|
-
}) ??
|
|
332
|
-
} catch (
|
|
333
|
-
e.logger.warn("[pontive] could not reach the issuer to end its session:",
|
|
381
|
+
sessionId: u?.sessionId
|
|
382
|
+
}) ?? f;
|
|
383
|
+
} catch (w) {
|
|
384
|
+
e.logger.warn("[pontive] could not reach the issuer to end its session:", w instanceof Error ? w.message : String(w));
|
|
334
385
|
}
|
|
335
|
-
return m(
|
|
386
|
+
return m(f, l);
|
|
336
387
|
}
|
|
337
|
-
async function
|
|
388
|
+
async function X(o) {
|
|
338
389
|
try {
|
|
339
|
-
const i = await
|
|
390
|
+
const i = await ce(r, e.fetch, o.refreshToken);
|
|
340
391
|
return {
|
|
341
392
|
...o,
|
|
342
393
|
accessToken: i.access_token,
|
|
343
394
|
// A response without one means rotation is off: the token in hand is still current.
|
|
344
395
|
refreshToken: i.refresh_token ?? o.refreshToken,
|
|
345
|
-
expiresAt:
|
|
396
|
+
expiresAt: j(i)
|
|
346
397
|
};
|
|
347
398
|
} catch (i) {
|
|
348
399
|
if (i instanceof W && i.status >= 400 && i.status < 500)
|
|
@@ -354,38 +405,42 @@ function me(t) {
|
|
|
354
405
|
async handle(o) {
|
|
355
406
|
const { pathname: i } = new URL(o.url);
|
|
356
407
|
if (!i.startsWith(`${e.basePath}/`)) return null;
|
|
357
|
-
const
|
|
358
|
-
return
|
|
408
|
+
const u = i.slice(e.basePath.length + 1);
|
|
409
|
+
return u === "login" && o.method === "GET" ? G(o) : u === "callback" && o.method === "GET" ? z(o) : u === "logout" && (o.method === "GET" || o.method === "POST") ? B(o) : null;
|
|
359
410
|
},
|
|
360
411
|
async getSession(o) {
|
|
361
|
-
const i = await
|
|
412
|
+
const i = await h(S(o));
|
|
362
413
|
return i ? Date.now() >= i.expiresAt ? (e.logger.warn(
|
|
363
414
|
"[pontive] the session's access token has expired and getSession cannot refresh it. Run the SDK's middleware on this path so it refreshes before the request is handled."
|
|
364
|
-
), null) :
|
|
415
|
+
), null) : y(i) : null;
|
|
365
416
|
},
|
|
366
417
|
async refresh(o) {
|
|
367
|
-
const i =
|
|
368
|
-
session:
|
|
418
|
+
const i = S(o.headers.get("cookie")), u = (p) => ({
|
|
419
|
+
session: p,
|
|
369
420
|
setCookies: [],
|
|
370
421
|
cookieHeader: o.headers.get("cookie") ?? ""
|
|
371
|
-
}), l = await
|
|
372
|
-
if (!l) return
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
if (
|
|
376
|
-
|
|
422
|
+
}), l = await h(i);
|
|
423
|
+
if (!l) return u(null);
|
|
424
|
+
if (new URL(o.url).pathname.startsWith(`${e.basePath}/`))
|
|
425
|
+
return u(Date.now() < l.expiresAt ? y(l) : null);
|
|
426
|
+
if (Date.now() < l.expiresAt - e.refreshSkewSeconds * 1e3) return u(y(l));
|
|
427
|
+
const f = () => ({ session: null, setCookies: R(i, e.cookieName, a(o)), cookieHeader: $(i) });
|
|
428
|
+
if (!l.refreshToken) return f();
|
|
429
|
+
let w;
|
|
377
430
|
try {
|
|
378
|
-
|
|
379
|
-
} catch (
|
|
380
|
-
return e.logger.warn("[pontive] refresh failed, will retry:",
|
|
431
|
+
w = await s.run(l.refreshToken, () => X(l));
|
|
432
|
+
} catch (p) {
|
|
433
|
+
return e.logger.warn("[pontive] refresh failed, will retry:", p instanceof Error ? p.message : String(p)), u(Date.now() < l.expiresAt ? y(l) : null);
|
|
381
434
|
}
|
|
382
|
-
if (!
|
|
383
|
-
const
|
|
384
|
-
return { session:
|
|
435
|
+
if (!w) return f();
|
|
436
|
+
const k = await _(i, w, o);
|
|
437
|
+
return { session: y(w), setCookies: k, cookieHeader: $(i) };
|
|
385
438
|
}
|
|
386
439
|
};
|
|
387
440
|
}
|
|
388
441
|
export {
|
|
389
|
-
|
|
442
|
+
le as ACCESS_COOKIE,
|
|
443
|
+
he as SESSION_HINT_COOKIE,
|
|
444
|
+
Ce as createServerAuth
|
|
390
445
|
};
|
|
391
446
|
//# sourceMappingURL=index.js.map
|