@pofsis-nbt/pofsis-auth 2.0.1 → 2.1.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/Documentation.md +151 -147
- package/README.md +143 -133
- package/dist/PofsisAuth.d.ts +1 -1
- package/dist/PofsisAuth.d.ts.map +1 -1
- package/dist/{PofsisAuthClient-CEw_lL5S.js → PofsisAuthClient-Duybofpq.js} +162 -46
- package/dist/PofsisAuthClient-Duybofpq.js.map +1 -0
- package/dist/PofsisAuthClient-c4lzLzjV.cjs +2 -0
- package/dist/PofsisAuthClient-c4lzLzjV.cjs.map +1 -0
- package/dist/{RequireAuth-CPhXupYh.cjs → RequireAuth-BkYhk-9p.cjs} +2 -2
- package/dist/{RequireAuth-CPhXupYh.cjs.map → RequireAuth-BkYhk-9p.cjs.map} +1 -1
- package/dist/{RequireAuth-DFa8_MR1.js → RequireAuth-DroX56rd.js} +67 -62
- package/dist/{RequireAuth-DFa8_MR1.js.map → RequireAuth-DroX56rd.js.map} +1 -1
- package/dist/auth/authLaunch.d.ts.map +1 -1
- package/dist/auth/config.d.ts.map +1 -1
- package/dist/core/PofsisAuthClient.d.ts +2 -0
- package/dist/core/PofsisAuthClient.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/popupProtocol.d.ts +11 -1
- package/dist/core/popupProtocol.d.ts.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.js +2 -2
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.cjs.map +1 -1
- package/dist/elements.js +8 -3
- package/dist/elements.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/pofsis-auth-elements.js +1 -1
- package/dist/pofsis-auth-elements.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.js +1 -1
- package/dist/types.d.ts +13 -2
- package/dist/types.d.ts.map +1 -1
- package/docs/popup-integration.md +188 -162
- package/package.json +87 -87
- package/dist/PofsisAuthClient-B3YHqgZL.cjs +0 -2
- package/dist/PofsisAuthClient-B3YHqgZL.cjs.map +0 -1
- package/dist/PofsisAuthClient-CEw_lL5S.js.map +0 -1
|
@@ -100,19 +100,26 @@ function f(e = {}) {
|
|
|
100
100
|
height: e.popup?.height ?? 720,
|
|
101
101
|
name: e.popup?.name?.trim() || "pofsis-auth",
|
|
102
102
|
timeoutMs: e.popup?.timeoutMs ?? 3e5
|
|
103
|
-
}, s =
|
|
104
|
-
|
|
103
|
+
}, s = {
|
|
104
|
+
width: e.modal?.width ?? 480,
|
|
105
|
+
height: e.modal?.height ?? 720,
|
|
106
|
+
timeoutMs: e.modal?.timeoutMs ?? 3e5,
|
|
107
|
+
readyTimeoutMs: e.modal?.readyTimeoutMs ?? 15e3
|
|
108
|
+
}, c = [];
|
|
109
|
+
if (t || c.push("applicationId"), n || c.push("apiBaseUrl"), r || c.push("authUrl"), c.length) throw Error(`@pofsis-nbt/pofsis-auth missing config: ${c.join(", ")}`);
|
|
105
110
|
if (!t || !n || !r) throw Error("@pofsis-nbt/pofsis-auth missing config");
|
|
106
111
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t)) throw Error("@pofsis-nbt/pofsis-auth applicationId must be a UUID");
|
|
107
112
|
if (!a.startsWith("/") || a.startsWith("//")) throw Error("@pofsis-nbt/pofsis-auth callbackPath must be application-relative");
|
|
108
113
|
if (o.width <= 0 || o.height <= 0 || o.timeoutMs <= 0) throw Error("@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive");
|
|
114
|
+
if (s.width <= 0 || s.height <= 0 || s.timeoutMs <= 0 || s.readyTimeoutMs <= 0) throw Error("@pofsis-nbt/pofsis-auth modal dimensions and timeouts must be positive");
|
|
109
115
|
return {
|
|
110
116
|
applicationId: t.toLowerCase(),
|
|
111
117
|
apiBaseUrl: d(n),
|
|
112
118
|
authUrl: d(r),
|
|
113
119
|
scope: i,
|
|
114
120
|
callbackPath: a,
|
|
115
|
-
popup: o
|
|
121
|
+
popup: o,
|
|
122
|
+
modal: s
|
|
116
123
|
};
|
|
117
124
|
}
|
|
118
125
|
//#endregion
|
|
@@ -152,42 +159,43 @@ function b(e) {
|
|
|
152
159
|
}
|
|
153
160
|
function x({ authUrl: e, query: t, options: n }) {
|
|
154
161
|
let r = y(n), i = new URL(e);
|
|
155
|
-
if (i.search = t.toString(), r.loginHint && i.searchParams.set("login_hint", r.loginHint), r.screen === "login" && r.method && i.searchParams.set("method", r.method), r.screen === "login") return i.toString();
|
|
162
|
+
if (i.search = t.toString(), n?.presentation === "modal" && i.searchParams.set("presentation", "modal"), r.loginHint && i.searchParams.set("login_hint", r.loginHint), r.screen === "login" && r.method && i.searchParams.set("method", r.method), r.screen === "login") return i.toString();
|
|
156
163
|
let a = r.screen === "signup" ? "/signup" : "/forgot-password", o = new URL(a, i), s = t.get("client_id");
|
|
157
|
-
return s && o.searchParams.set("client_id", s), o.searchParams.set("return_to", `${i.pathname}${i.search}`), r.loginHint && o.searchParams.set("login_hint", r.loginHint), r.screen === "signup" && o.searchParams.set("method", r.method || "password"), o.toString();
|
|
164
|
+
return s && o.searchParams.set("client_id", s), n?.presentation === "modal" && o.searchParams.set("presentation", "modal"), o.searchParams.set("return_to", `${i.pathname}${i.search}`), r.loginHint && o.searchParams.set("login_hint", r.loginHint), r.screen === "signup" && o.searchParams.set("method", r.method || "password"), o.toString();
|
|
158
165
|
}
|
|
159
166
|
//#endregion
|
|
160
167
|
//#region src/core/popupProtocol.ts
|
|
161
|
-
var S = "pofsis-auth:callback";
|
|
162
|
-
function
|
|
168
|
+
var S = "pofsis-auth:callback", C = "pofsis-auth:frame-init";
|
|
169
|
+
function w(e) {
|
|
163
170
|
if (!e) return;
|
|
164
171
|
let t = e.indexOf(".");
|
|
165
172
|
return t > 0 ? e.slice(0, t) : void 0;
|
|
166
173
|
}
|
|
167
|
-
function
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
function T(e = window.location.origin) {
|
|
175
|
+
let t = new URLSearchParams(window.location.search), n = t.get("state") || void 0, r = w(n || null);
|
|
176
|
+
if (!r) return !1;
|
|
177
|
+
let i = window.opener && !window.opener.closed ? window.opener : null, a = window.parent === window ? null : window.parent, o = i || a;
|
|
178
|
+
if (!o) return !1;
|
|
179
|
+
let s = {
|
|
170
180
|
type: S,
|
|
171
181
|
code: t.get("code") || void 0,
|
|
172
182
|
state: n,
|
|
173
183
|
error: t.get("error") || void 0,
|
|
174
|
-
correlationId:
|
|
184
|
+
correlationId: r
|
|
175
185
|
};
|
|
176
|
-
return
|
|
186
|
+
return o.postMessage(s, e), i && window.close(), !0;
|
|
177
187
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
async function D(e) {
|
|
182
|
-
return T(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e))));
|
|
188
|
+
var E = T, D = (e) => btoa(String.fromCharCode(...e)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""), O = () => D(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32)));
|
|
189
|
+
async function k(e) {
|
|
190
|
+
return D(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e))));
|
|
183
191
|
}
|
|
184
192
|
//#endregion
|
|
185
193
|
//#region src/core/PofsisAuthClient.ts
|
|
186
|
-
var
|
|
194
|
+
var A = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, j = (e) => ({
|
|
187
195
|
token_type: e.token_type,
|
|
188
196
|
expires_in: e.expires_in,
|
|
189
197
|
user: e.user
|
|
190
|
-
}),
|
|
198
|
+
}), M = class {
|
|
191
199
|
config;
|
|
192
200
|
token = null;
|
|
193
201
|
session = null;
|
|
@@ -206,7 +214,7 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
206
214
|
destroy() {
|
|
207
215
|
window.removeEventListener("message", this.onPopupMessage), this.listening = !1;
|
|
208
216
|
let e = this.finishAttempt();
|
|
209
|
-
e &&
|
|
217
|
+
e && e.resolve({ status: "cancelled" }), this.subscribers.clear();
|
|
210
218
|
}
|
|
211
219
|
getUser() {
|
|
212
220
|
return this.session?.user ?? null;
|
|
@@ -226,7 +234,7 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
226
234
|
for (let e of this.subscribers) e(this.session);
|
|
227
235
|
}
|
|
228
236
|
accept(e) {
|
|
229
|
-
this.token = e.access_token, this.session =
|
|
237
|
+
this.token = e.access_token, this.session = j(e), this.emit();
|
|
230
238
|
}
|
|
231
239
|
loadClient() {
|
|
232
240
|
return this.clientPromise ||= n(this.config).then((e) => this.client = e).catch((e) => {
|
|
@@ -274,8 +282,11 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
274
282
|
});
|
|
275
283
|
}
|
|
276
284
|
async login(e = {}) {
|
|
277
|
-
let t = y(e);
|
|
278
|
-
return
|
|
285
|
+
let t = y(e), n = e.presentation ?? "popup";
|
|
286
|
+
return n === "popup" ? this.openPopup({
|
|
287
|
+
...e,
|
|
288
|
+
...t
|
|
289
|
+
}) : n === "modal" ? this.openModal({
|
|
279
290
|
...e,
|
|
280
291
|
...t
|
|
281
292
|
}) : this.startRedirect({
|
|
@@ -290,7 +301,7 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
290
301
|
response_type: "code",
|
|
291
302
|
scope: this.config.scope,
|
|
292
303
|
state: t,
|
|
293
|
-
code_challenge: await
|
|
304
|
+
code_challenge: await k(n),
|
|
294
305
|
code_challenge_method: "S256"
|
|
295
306
|
});
|
|
296
307
|
return x({
|
|
@@ -303,26 +314,19 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
303
314
|
return `${this.config.applicationId}.auth.${e}`;
|
|
304
315
|
}
|
|
305
316
|
async startRedirect(e) {
|
|
306
|
-
let t =
|
|
317
|
+
let t = O(), n = O();
|
|
307
318
|
sessionStorage.setItem(this.storageKey("state"), t), sessionStorage.setItem(this.storageKey("verifier"), n);
|
|
308
|
-
let r =
|
|
319
|
+
let r = A(e.returnUrl);
|
|
309
320
|
return r ? sessionStorage.setItem(this.storageKey("return-path"), r) : sessionStorage.removeItem(this.storageKey("return-path")), window.location.assign(await this.authorizationUrl(e, t, n)), { status: "redirecting" };
|
|
310
321
|
}
|
|
311
322
|
async openPopup(e) {
|
|
312
|
-
if (this.attempt
|
|
313
|
-
let n = this.attempt, r = n.resolve, i = n.reject;
|
|
314
|
-
n.resolve = (t) => {
|
|
315
|
-
r(t), e(t);
|
|
316
|
-
}, n.reject = (e) => {
|
|
317
|
-
i(e), t(e);
|
|
318
|
-
};
|
|
319
|
-
});
|
|
323
|
+
if (this.attempt) return this.joinAttempt(this.attempt);
|
|
320
324
|
let { width: t, height: n, name: r, timeoutMs: i } = this.config.popup, a = Math.max(0, window.screenX + (window.outerWidth - t) / 2), o = Math.max(0, window.screenY + (window.outerHeight - n) / 2), s = window.open("about:blank", r, `popup=yes,width=${t},height=${n},left=${Math.round(a)},top=${Math.round(o)}`);
|
|
321
325
|
if (!s) return this.startRedirect({
|
|
322
326
|
...e,
|
|
323
327
|
presentation: "redirect"
|
|
324
328
|
});
|
|
325
|
-
let c =
|
|
329
|
+
let c = O(), l = `${c}.${O()}`, u = O(), d = A(e.returnUrl);
|
|
326
330
|
return new Promise((t, n) => {
|
|
327
331
|
let r = setInterval(() => {
|
|
328
332
|
s.closed && this.finishAttempt()?.resolve({ status: "cancelled" });
|
|
@@ -331,7 +335,8 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
331
335
|
s.close(), e?.reject(/* @__PURE__ */ Error("POFSIS Auth popup timed out."));
|
|
332
336
|
}, i);
|
|
333
337
|
this.attempt = {
|
|
334
|
-
|
|
338
|
+
presentation: "popup",
|
|
339
|
+
source: s,
|
|
335
340
|
state: l,
|
|
336
341
|
verifier: u,
|
|
337
342
|
correlationId: c,
|
|
@@ -339,33 +344,144 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
339
344
|
resolve: t,
|
|
340
345
|
reject: n,
|
|
341
346
|
timer: r,
|
|
342
|
-
timeout: a
|
|
347
|
+
timeout: a,
|
|
348
|
+
focus: () => s.focus(),
|
|
349
|
+
cleanup: () => s.close()
|
|
343
350
|
}, this.authorizationUrl(e, l, u).then((e) => s.location.replace(e)).catch((e) => {
|
|
344
351
|
let t = this.finishAttempt();
|
|
345
352
|
s.close(), t?.reject(e instanceof Error ? e : Error(String(e)));
|
|
346
353
|
});
|
|
347
354
|
});
|
|
348
355
|
}
|
|
356
|
+
async openModal(e) {
|
|
357
|
+
if (this.attempt) return this.joinAttempt(this.attempt);
|
|
358
|
+
let { width: t, height: n, timeoutMs: r, readyTimeoutMs: i } = this.config.modal, a = document.activeElement instanceof HTMLElement ? document.activeElement : null, o = document.createElement("dialog"), s = document.createElement("div"), c = document.createElement("span"), l = document.createElement("button"), u = document.createElement("iframe");
|
|
359
|
+
o.setAttribute("aria-label", "POFSIS authentication"), o.dataset.pofsisAuthModal = "", Object.assign(o.style, {
|
|
360
|
+
width: `min(${t}px, calc(100vw - 32px))`,
|
|
361
|
+
height: `min(${n}px, calc(100dvh - 32px))`,
|
|
362
|
+
maxWidth: "none",
|
|
363
|
+
maxHeight: "none",
|
|
364
|
+
padding: "0",
|
|
365
|
+
border: "0",
|
|
366
|
+
borderRadius: "12px",
|
|
367
|
+
boxShadow: "0 24px 80px rgba(0, 0, 0, 0.28)",
|
|
368
|
+
overflow: "hidden"
|
|
369
|
+
}), Object.assign(s.style, {
|
|
370
|
+
height: "48px",
|
|
371
|
+
padding: "0 10px 0 16px",
|
|
372
|
+
display: "flex",
|
|
373
|
+
alignItems: "center",
|
|
374
|
+
justifyContent: "space-between",
|
|
375
|
+
background: "#fff",
|
|
376
|
+
borderBottom: "1px solid rgba(0, 0, 0, 0.10)",
|
|
377
|
+
font: "500 14px/20px Inter, sans-serif"
|
|
378
|
+
}), c.textContent = e.screen === "signup" ? "Create account" : e.screen === "reset" ? "Reset password" : "Sign in", l.type = "button", l.setAttribute("aria-label", "Close authentication"), l.textContent = "×", Object.assign(l.style, {
|
|
379
|
+
width: "36px",
|
|
380
|
+
height: "36px",
|
|
381
|
+
padding: "0",
|
|
382
|
+
border: "0",
|
|
383
|
+
borderRadius: "8px",
|
|
384
|
+
background: "transparent",
|
|
385
|
+
color: "#0a0a0a",
|
|
386
|
+
cursor: "pointer",
|
|
387
|
+
font: "400 26px/36px sans-serif"
|
|
388
|
+
}), u.title = c.textContent, u.setAttribute("sandbox", "allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox"), u.setAttribute("allow", "publickey-credentials-get *; publickey-credentials-create *"), Object.assign(u.style, {
|
|
389
|
+
display: "block",
|
|
390
|
+
width: "100%",
|
|
391
|
+
height: "calc(100% - 48px)",
|
|
392
|
+
border: "0",
|
|
393
|
+
background: "#fff"
|
|
394
|
+
}), s.append(c, l), o.append(s, u), document.body.append(o);
|
|
395
|
+
let d = "pofsis-auth-modal-style";
|
|
396
|
+
if (!document.getElementById(d)) {
|
|
397
|
+
let e = document.createElement("style");
|
|
398
|
+
e.id = d, e.textContent = "[data-pofsis-auth-modal]::backdrop{background:rgba(10,10,10,.56);backdrop-filter:blur(2px)}", document.head.append(e);
|
|
399
|
+
}
|
|
400
|
+
let f = O(), p = `${f}.${O()}`, m = O(), h = A(e.returnUrl);
|
|
401
|
+
return new Promise((t, n) => {
|
|
402
|
+
let s, c = () => {
|
|
403
|
+
this.attempt === s && this.finishAttempt()?.resolve({ status: "cancelled" });
|
|
404
|
+
};
|
|
405
|
+
l.addEventListener("click", c), o.addEventListener("cancel", (e) => {
|
|
406
|
+
e.preventDefault(), c();
|
|
407
|
+
}), o.addEventListener("click", (e) => {
|
|
408
|
+
if (e.target !== o) return;
|
|
409
|
+
let t = o.getBoundingClientRect();
|
|
410
|
+
(e.clientX < t.left || e.clientX > t.right || e.clientY < t.top || e.clientY > t.bottom) && c();
|
|
411
|
+
});
|
|
412
|
+
let d = setTimeout(() => {
|
|
413
|
+
this.finishAttempt()?.reject(/* @__PURE__ */ Error("POFSIS Auth modal timed out."));
|
|
414
|
+
}, r), g = u.contentWindow;
|
|
415
|
+
if (!g) {
|
|
416
|
+
o.remove(), clearTimeout(d), n(/* @__PURE__ */ Error("POFSIS Auth modal could not be created."));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
s = {
|
|
420
|
+
presentation: "modal",
|
|
421
|
+
source: g,
|
|
422
|
+
state: p,
|
|
423
|
+
verifier: m,
|
|
424
|
+
correlationId: f,
|
|
425
|
+
returnUrl: h,
|
|
426
|
+
resolve: t,
|
|
427
|
+
reject: n,
|
|
428
|
+
timeout: d,
|
|
429
|
+
focus: () => l.focus(),
|
|
430
|
+
cleanup: () => {
|
|
431
|
+
o.remove(), a?.focus();
|
|
432
|
+
}
|
|
433
|
+
}, this.attempt = s, o.showModal(), l.focus(), this.authorizationUrl(e, p, m).then((e) => {
|
|
434
|
+
if (this.attempt !== s) return;
|
|
435
|
+
let t = new URL(e).origin;
|
|
436
|
+
s.authOrigin = t;
|
|
437
|
+
let n = {
|
|
438
|
+
type: C,
|
|
439
|
+
state: p,
|
|
440
|
+
correlationId: f,
|
|
441
|
+
applicationId: this.config.applicationId
|
|
442
|
+
}, r = () => u.contentWindow?.postMessage(n, t);
|
|
443
|
+
u.addEventListener("load", r), u.src = e, r(), s.timer = setInterval(r, 250), s.readyTimeout = setTimeout(() => {
|
|
444
|
+
this.finishAttempt()?.reject(/* @__PURE__ */ Error("POFSIS Auth modal could not be embedded."));
|
|
445
|
+
}, i);
|
|
446
|
+
}).catch((e) => {
|
|
447
|
+
this.finishAttempt()?.reject(e instanceof Error ? e : Error(String(e)));
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
joinAttempt(e) {
|
|
452
|
+
return e.focus(), new Promise((t, n) => {
|
|
453
|
+
let r = e.resolve, i = e.reject;
|
|
454
|
+
e.resolve = (e) => {
|
|
455
|
+
r(e), t(e);
|
|
456
|
+
}, e.reject = (e) => {
|
|
457
|
+
i(e), n(e);
|
|
458
|
+
};
|
|
459
|
+
});
|
|
460
|
+
}
|
|
349
461
|
finishAttempt() {
|
|
350
462
|
let e = this.attempt;
|
|
351
|
-
return e ? (clearInterval(e.timer), clearTimeout(e.timeout), this.attempt = null, e) : null;
|
|
463
|
+
return e ? (e.timer && clearInterval(e.timer), clearTimeout(e.timeout), e.readyTimeout && clearTimeout(e.readyTimeout), this.attempt = null, e.cleanup(), e) : null;
|
|
352
464
|
}
|
|
353
465
|
onPopupMessage = (e) => {
|
|
354
466
|
let t = this.attempt, n = e.data;
|
|
355
|
-
if (
|
|
467
|
+
if (t?.presentation === "modal" && n?.type === "pofsis-auth:frame-ready" && e.origin === t.authOrigin && e.source === t.source && n.applicationId === this.config.applicationId && n.correlationId === t.correlationId && n.state === t.state) {
|
|
468
|
+
t.ready = !0, t.timer && clearInterval(t.timer), t.readyTimeout && clearTimeout(t.readyTimeout), t.timer = void 0, t.readyTimeout = void 0;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (!t || t.presentation === "modal" && !t.ready || e.origin !== window.location.origin || e.source !== t.source || n?.type !== "pofsis-auth:callback" || n.correlationId !== t.correlationId || w(n.state || null) !== t.correlationId || n.state !== t.state) return;
|
|
356
472
|
let r = this.finishAttempt();
|
|
357
473
|
if (r) {
|
|
358
474
|
if (n.error || !n.code) {
|
|
359
|
-
r.
|
|
475
|
+
r.reject(Error(n.error || "POFSIS Auth callback was incomplete."));
|
|
360
476
|
return;
|
|
361
477
|
}
|
|
362
478
|
this.completeCode(n.code, n.state, r.verifier).then(() => {
|
|
363
|
-
r.
|
|
479
|
+
r.returnUrl && window.history.replaceState(null, "", r.returnUrl), r.resolve({
|
|
364
480
|
status: "authenticated",
|
|
365
481
|
user: this.getUser()
|
|
366
482
|
});
|
|
367
483
|
}).catch((e) => {
|
|
368
|
-
r.
|
|
484
|
+
r.reject(e instanceof Error ? e : Error(String(e)));
|
|
369
485
|
});
|
|
370
486
|
}
|
|
371
487
|
};
|
|
@@ -380,10 +496,10 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
|
|
|
380
496
|
await this.completeCode(e, t, r);
|
|
381
497
|
}
|
|
382
498
|
};
|
|
383
|
-
function
|
|
384
|
-
return new
|
|
499
|
+
function N(e) {
|
|
500
|
+
return new M(e);
|
|
385
501
|
}
|
|
386
502
|
//#endregion
|
|
387
|
-
export {
|
|
503
|
+
export { b as a, s as c, E as i, c as l, N as n, f as o, T as r, u as s, M as t, l as u };
|
|
388
504
|
|
|
389
|
-
//# sourceMappingURL=PofsisAuthClient-
|
|
505
|
+
//# sourceMappingURL=PofsisAuthClient-Duybofpq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PofsisAuthClient-Duybofpq.js","names":[],"sources":["../src/auth/api.ts","../src/auth/config.ts","../src/auth/authLaunch.ts","../src/core/popupProtocol.ts","../src/auth/pkce.ts","../src/core/PofsisAuthClient.ts"],"sourcesContent":["import type { AccountProfile, OAuthClientConfig, PofsisAuthConfig, TokenResponse } from '../types'\r\n\r\nasync function parseJson<T>(response: Response): Promise<T> {\r\n if (response.status === 204) return null as T\r\n const text = await response.text()\r\n if (!text) return null as T\r\n return JSON.parse(text) as T\r\n}\r\n\r\nasync function request<T>(\r\n config: PofsisAuthConfig,\r\n path: string,\r\n init?: RequestInit,\r\n): Promise<{ status: number; data: T }> {\r\n const response = await fetch(`${config.apiBaseUrl}${path}`, {\r\n credentials: 'include',\r\n ...init,\r\n headers: {\r\n Accept: 'application/json',\r\n ...(init?.body && !(init.body instanceof FormData)\r\n ? { 'Content-Type': 'application/json' }\r\n : {}),\r\n ...init?.headers,\r\n },\r\n })\r\n if (!response.ok) {\r\n const error = new Error(`Auth API ${path} failed (${response.status})`)\r\n ;(error as Error & { status?: number }).status = response.status\r\n throw error\r\n }\r\n return { status: response.status, data: await parseJson<T>(response) }\r\n}\r\n\r\nexport async function fetchOAuthClient(config: PofsisAuthConfig) {\r\n const applicationId = encodeURIComponent(config.applicationId)\r\n const origin = encodeURIComponent(window.location.origin)\r\n const { data } = await request<OAuthClientConfig>(\r\n config,\r\n `/oauth/applications/${applicationId}/client?origin=${origin}`,\r\n )\r\n return data\r\n}\r\n\r\nexport async function exchangeCode(\r\n config: PofsisAuthConfig,\r\n code: string,\r\n verifier: string,\r\n client: Pick<OAuthClientConfig, 'client_id' | 'redirect_uri'>,\r\n) {\r\n const { data } = await request<TokenResponse>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'authorization_code',\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n code,\r\n code_verifier: verifier,\r\n }),\r\n })\r\n return data\r\n}\r\n\r\nexport async function refresh(config: PofsisAuthConfig, clientId: string) {\r\n const { data } = await request<TokenResponse | null>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n client_id: clientId,\r\n }),\r\n })\r\n return data || null\r\n}\r\n\r\nexport async function checkSession(config: PofsisAuthConfig) {\r\n try {\r\n await request(config, '/auth/session')\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nexport async function signOut(config: PofsisAuthConfig) {\r\n await request(config, '/auth/logout', { method: 'POST' })\r\n}\r\n\r\nexport async function getAccountProfile(config: PofsisAuthConfig, accessToken: string) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n\r\nexport async function updateAccountProfile(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n profile: { firstName?: string | null; lastName?: string | null },\r\n) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n method: 'PATCH',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body: JSON.stringify(profile),\r\n })\r\n return data\r\n}\r\n\r\nexport async function uploadAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n file: File,\r\n) {\r\n const body = new FormData()\r\n body.append('file', file)\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'POST',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body,\r\n })\r\n return data\r\n}\r\n\r\nexport async function deleteAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n) {\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'DELETE',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n","import type { PofsisAuthClientConfig, ResolvedPofsisAuthConfig } from '../types'\n\nfunction stripTrailingSlash(value: string) {\n return value.replace(/\\/$/, '')\n}\n\nexport type ConfigOverrides = Partial<PofsisAuthClientConfig>\n\n/**\n * Validate and normalize explicitly supplied runtime configuration.\n */\nexport function resolveConfig(overrides: ConfigOverrides = {}): ResolvedPofsisAuthConfig {\n const applicationId = overrides.applicationId?.trim()\n const apiBaseUrl = overrides.apiBaseUrl?.trim()\n const authUrl = overrides.authUrl?.trim()\n const scope = overrides.scope?.trim() || 'openid profile email'\n const callbackPath = overrides.callbackPath?.trim() || '/auth/callback'\n const popup = {\n width: overrides.popup?.width ?? 480,\n height: overrides.popup?.height ?? 720,\n name: overrides.popup?.name?.trim() || 'pofsis-auth',\n timeoutMs: overrides.popup?.timeoutMs ?? 300_000,\n }\n const modal = {\n width: overrides.modal?.width ?? 480,\n height: overrides.modal?.height ?? 720,\n timeoutMs: overrides.modal?.timeoutMs ?? 300_000,\n readyTimeoutMs: overrides.modal?.readyTimeoutMs ?? 15_000,\n }\n\n const missing: string[] = []\n if (!applicationId) missing.push('applicationId')\n if (!apiBaseUrl) missing.push('apiBaseUrl')\n if (!authUrl) missing.push('authUrl')\n if (missing.length) {\n throw new Error(`@pofsis-nbt/pofsis-auth missing config: ${missing.join(', ')}`)\n }\n if (!applicationId || !apiBaseUrl || !authUrl) {\n throw new Error('@pofsis-nbt/pofsis-auth missing config')\n }\n if (\n !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n applicationId,\n )\n ) {\n throw new Error('@pofsis-nbt/pofsis-auth applicationId must be a UUID')\n }\n if (!callbackPath.startsWith('/') || callbackPath.startsWith('//')) {\n throw new Error('@pofsis-nbt/pofsis-auth callbackPath must be application-relative')\n }\n if (popup.width <= 0 || popup.height <= 0 || popup.timeoutMs <= 0) {\n throw new Error('@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive')\n }\n if (\n modal.width <= 0 ||\n modal.height <= 0 ||\n modal.timeoutMs <= 0 ||\n modal.readyTimeoutMs <= 0\n ) {\n throw new Error('@pofsis-nbt/pofsis-auth modal dimensions and timeouts must be positive')\n }\n\n return {\n applicationId: applicationId.toLowerCase(),\n apiBaseUrl: stripTrailingSlash(apiBaseUrl),\n authUrl: stripTrailingSlash(authUrl),\n scope,\n callbackPath,\n popup,\n modal,\n }\n}\n","import type { AuthLaunchOptions, AuthMethod, AuthScreen } from '../types'\n\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst PHILIPPINE_MOBILE = /^(?:\\+63|63|0)?9\\d{9}$/\nconst METHODS = new Set<AuthMethod>(['password', 'passkey', 'otp'])\nconst SCREENS = new Set<AuthScreen>(['login', 'signup', 'reset'])\nconst MAX_HINT_LENGTH = 320\n\nfunction normalizeHint(value: unknown, emailOnly = false): string | undefined {\n const candidate = typeof value === 'string' ? value.trim() : ''\n if (!candidate || candidate.length > MAX_HINT_LENGTH) return undefined\n if (EMAIL.test(candidate)) return candidate.toLowerCase()\n const compact = candidate.replace(/[\\s()-]/g, '')\n if (emailOnly || !PHILIPPINE_MOBILE.test(compact)) return undefined\n return `+63${compact.replace(/^(?:\\+63|63|0)/, '')}`\n}\n\nexport function normalizeAuthLaunchOptions(\n value?: AuthLaunchOptions | string | null,\n defaultScreen: AuthScreen = 'login',\n) {\n const options = typeof value === 'string' ? { returnUrl: value } : value || {}\n const requestedScreen = options.screen === 'register' ? 'signup' : options.screen\n const screen = SCREENS.has(requestedScreen as AuthScreen)\n ? (requestedScreen as AuthScreen)\n : defaultScreen\n const requestedMethod = METHODS.has(options.method as AuthMethod)\n ? (options.method as AuthMethod)\n : undefined\n const method =\n screen === 'login' ||\n (screen === 'signup' && (requestedMethod === 'password' || requestedMethod === 'otp'))\n ? requestedMethod\n : undefined\n return {\n returnUrl: options.returnUrl,\n screen,\n loginHint: normalizeHint(options.loginHint),\n method,\n }\n}\n\nexport function authLaunchOptionsFromSearch(search: string) {\n const params = new URLSearchParams(search)\n const canonicalHint = params.get('login_hint')\n const loginHint =\n canonicalHint !== null\n ? normalizeHint(canonicalHint)\n : normalizeHint(params.get('email'), true)\n return normalizeAuthLaunchOptions({\n screen: (params.get('screen') || undefined) as AuthLaunchOptions['screen'],\n loginHint,\n method: (params.get('method') || undefined) as AuthLaunchOptions['method'],\n })\n}\n\nexport function buildAuthDestination({\n authUrl,\n query,\n options,\n}: {\n authUrl: string\n query: URLSearchParams\n options?: AuthLaunchOptions\n}) {\n const launch = normalizeAuthLaunchOptions(options)\n const authorizationUrl = new URL(authUrl)\n authorizationUrl.search = query.toString()\n if (options?.presentation === 'modal') {\n authorizationUrl.searchParams.set('presentation', 'modal')\n }\n if (launch.loginHint) authorizationUrl.searchParams.set('login_hint', launch.loginHint)\n if (launch.screen === 'login' && launch.method) {\n authorizationUrl.searchParams.set('method', launch.method)\n }\n if (launch.screen === 'login') return authorizationUrl.toString()\n\n const pathname = launch.screen === 'signup' ? '/signup' : '/forgot-password'\n const destination = new URL(pathname, authorizationUrl)\n const clientId = query.get('client_id')\n if (clientId) destination.searchParams.set('client_id', clientId)\n if (options?.presentation === 'modal') destination.searchParams.set('presentation', 'modal')\n destination.searchParams.set(\n 'return_to',\n `${authorizationUrl.pathname}${authorizationUrl.search}`,\n )\n if (launch.loginHint) destination.searchParams.set('login_hint', launch.loginHint)\n if (launch.screen === 'signup') {\n destination.searchParams.set('method', launch.method || 'password')\n }\n return destination.toString()\n}\n","export const POPUP_MESSAGE_TYPE = 'pofsis-auth:callback'\nexport const MODAL_INIT_MESSAGE_TYPE = 'pofsis-auth:frame-init'\nexport const MODAL_READY_MESSAGE_TYPE = 'pofsis-auth:frame-ready'\n\nexport type PopupCallbackMessage = {\n type: typeof POPUP_MESSAGE_TYPE\n code?: string\n state?: string\n error?: string\n correlationId?: string\n}\n\nexport type ModalProtocolMessage = {\n type: typeof MODAL_INIT_MESSAGE_TYPE | typeof MODAL_READY_MESSAGE_TYPE\n state: string\n correlationId: string\n applicationId: string\n}\n\nexport function correlationFromState(state: string | null) {\n if (!state) return undefined\n const separator = state.indexOf('.')\n return separator > 0 ? state.slice(0, separator) : undefined\n}\n\nexport function relayAuthCallback(targetOrigin = window.location.origin) {\n const params = new URLSearchParams(window.location.search)\n const state = params.get('state') || undefined\n const correlationId = correlationFromState(state || null)\n if (!correlationId) return false\n const opener = window.opener && !window.opener.closed ? window.opener : null\n const parent = window.parent !== window ? window.parent : null\n const recipient = opener || parent\n if (!recipient) return false\n const message: PopupCallbackMessage = {\n type: POPUP_MESSAGE_TYPE,\n code: params.get('code') || undefined,\n state,\n error: params.get('error') || undefined,\n correlationId,\n }\n recipient.postMessage(message, targetOrigin)\n if (opener) window.close()\n return true\n}\n\n/** @deprecated Use relayAuthCallback for both popup and modal callbacks. */\nexport const relayPopupCallback = relayAuthCallback\n","const encode = (bytes: Uint8Array) =>\r\n btoa(String.fromCharCode(...bytes))\r\n .replace(/\\+/g, '-')\r\n .replace(/\\//g, '_')\r\n .replace(/=+$/, '')\r\n\r\nexport const randomValue = () => encode(crypto.getRandomValues(new Uint8Array(32)))\r\n\r\nexport async function pkceChallenge(verifier: string) {\r\n return encode(\r\n new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))),\r\n )\r\n}\r\n","import { checkSession, exchangeCode, fetchOAuthClient, refresh, signOut } from '../auth/api'\nimport { buildAuthDestination, normalizeAuthLaunchOptions } from '../auth/authLaunch'\nimport { resolveConfig } from '../auth/config'\nimport { pkceChallenge, randomValue } from '../auth/pkce'\nimport type {\n AuthLaunchOptions,\n AuthResult,\n OAuthClientConfig,\n PofsisAuthClientConfig,\n ResolvedPofsisAuthConfig,\n PofsisUser,\n SessionPayload,\n} from '../types'\nimport {\n correlationFromState,\n MODAL_INIT_MESSAGE_TYPE,\n MODAL_READY_MESSAGE_TYPE,\n POPUP_MESSAGE_TYPE,\n type ModalProtocolMessage,\n type PopupCallbackMessage,\n} from './popupProtocol'\n\ntype Subscriber = (session: SessionPayload | null) => void\ntype AuthAttempt = {\n presentation: 'popup' | 'modal'\n source: Window\n state: string\n verifier: string\n correlationId: string\n returnUrl?: string\n resolve: (result: AuthResult) => void\n reject: (error: Error) => void\n timer?: ReturnType<typeof setInterval>\n timeout: ReturnType<typeof setTimeout>\n readyTimeout?: ReturnType<typeof setTimeout>\n ready?: boolean\n authOrigin?: string\n focus: () => void\n cleanup: () => void\n}\n\nconst safeLocalPath = (value?: string) =>\n value?.startsWith('/') && !value.startsWith('//') ? value : undefined\n\nconst toSession = (result: { token_type: string; expires_in: number; user: PofsisUser }) => ({\n token_type: result.token_type,\n expires_in: result.expires_in,\n user: result.user,\n})\n\nexport class PofsisAuthClient {\n readonly config: ResolvedPofsisAuthConfig\n private token: string | null = null\n private session: SessionPayload | null = null\n private client: OAuthClientConfig | null = null\n private clientPromise: Promise<OAuthClientConfig> | null = null\n private refreshPromise: Promise<void> | null = null\n private subscribers = new Set<Subscriber>()\n private attempt: AuthAttempt | null = null\n private listening = false\n\n constructor(config: PofsisAuthClientConfig) {\n this.config = resolveConfig(config)\n this.attach()\n }\n\n private attach() {\n if (this.listening) return\n window.addEventListener('message', this.onPopupMessage)\n this.listening = true\n }\n\n destroy() {\n window.removeEventListener('message', this.onPopupMessage)\n this.listening = false\n const attempt = this.finishAttempt()\n if (attempt) {\n attempt.resolve({ status: 'cancelled' })\n }\n this.subscribers.clear()\n }\n\n getUser() {\n return this.session?.user ?? null\n }\n\n getSession() {\n return this.session\n }\n\n getAccessToken() {\n return this.token\n }\n\n subscribe(listener: Subscriber) {\n this.attach()\n this.subscribers.add(listener)\n listener(this.session)\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n private emit() {\n for (const listener of this.subscribers) listener(this.session)\n }\n\n private accept(result: Awaited<ReturnType<typeof exchangeCode>>) {\n this.token = result.access_token\n this.session = toSession(result)\n this.emit()\n }\n\n private loadClient() {\n if (!this.clientPromise) {\n this.clientPromise = fetchOAuthClient(this.config)\n .then((client) => (this.client = client))\n .catch((error) => {\n this.clientPromise = null\n throw error\n })\n }\n return this.clientPromise\n }\n\n getOAuthClient() {\n return this.loadClient()\n }\n\n async refreshSession() {\n const client = await this.loadClient()\n if (!this.refreshPromise) {\n this.refreshPromise = refresh(this.config, client.client_id)\n .then((result) => {\n if (result) this.accept(result)\n else this.clearSession()\n })\n .finally(() => (this.refreshPromise = null))\n }\n return this.refreshPromise\n }\n\n async isRemoteSessionActive() {\n return checkSession(this.config)\n }\n\n clearSession() {\n this.token = null\n this.session = null\n this.emit()\n }\n\n replaceUser(user: PofsisUser) {\n if (!this.session) return\n this.session = { ...this.session, user }\n this.emit()\n }\n\n async logout() {\n try {\n await signOut(this.config)\n } finally {\n this.clearSession()\n }\n }\n\n signup(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\n return this.login({ ...options, screen: 'signup' })\n }\n\n resetPassword(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\n return this.login({ ...options, screen: 'reset' })\n }\n\n async login(options: AuthLaunchOptions = {}): Promise<AuthResult> {\n const launch = normalizeAuthLaunchOptions(options)\n const presentation = options.presentation ?? 'popup'\n if (presentation === 'popup') return this.openPopup({ ...options, ...launch })\n if (presentation === 'modal') return this.openModal({ ...options, ...launch })\n return this.startRedirect({ ...options, ...launch })\n }\n\n private async authorizationUrl(options: AuthLaunchOptions, state: string, verifier: string) {\n const client = await this.loadClient()\n const query = new URLSearchParams({\n client_id: client.client_id,\n redirect_uri: client.redirect_uri,\n response_type: 'code',\n scope: this.config.scope,\n state,\n code_challenge: await pkceChallenge(verifier),\n code_challenge_method: 'S256',\n })\n return buildAuthDestination({\n authUrl: this.config.authUrl,\n query,\n options,\n })\n }\n\n private storageKey(suffix: string) {\n return `${this.config.applicationId}.auth.${suffix}`\n }\n\n private async startRedirect(options: AuthLaunchOptions): Promise<AuthResult> {\n const state = randomValue()\n const verifier = randomValue()\n sessionStorage.setItem(this.storageKey('state'), state)\n sessionStorage.setItem(this.storageKey('verifier'), verifier)\n const returnUrl = safeLocalPath(options.returnUrl)\n if (returnUrl) sessionStorage.setItem(this.storageKey('return-path'), returnUrl)\n else sessionStorage.removeItem(this.storageKey('return-path'))\n window.location.assign(await this.authorizationUrl(options, state, verifier))\n return { status: 'redirecting' }\n }\n\n private async openPopup(options: AuthLaunchOptions): Promise<AuthResult> {\n if (this.attempt) return this.joinAttempt(this.attempt)\n const { width, height, name, timeoutMs } = this.config.popup\n const left = Math.max(0, window.screenX + (window.outerWidth - width) / 2)\n const top = Math.max(0, window.screenY + (window.outerHeight - height) / 2)\n const popup = window.open(\n 'about:blank',\n name,\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\n )\n if (!popup) return this.startRedirect({ ...options, presentation: 'redirect' })\n\n const correlationId = randomValue()\n const state = `${correlationId}.${randomValue()}`\n const verifier = randomValue()\n const returnUrl = safeLocalPath(options.returnUrl)\n return new Promise<AuthResult>((resolve, reject) => {\n const timer = setInterval(() => {\n if (!popup.closed) return\n const attempt = this.finishAttempt()\n attempt?.resolve({ status: 'cancelled' })\n }, 250)\n const timeout = setTimeout(() => {\n const attempt = this.finishAttempt()\n popup.close()\n attempt?.reject(new Error('POFSIS Auth popup timed out.'))\n }, timeoutMs)\n this.attempt = {\n presentation: 'popup',\n source: popup,\n state,\n verifier,\n correlationId,\n returnUrl,\n resolve,\n reject,\n timer,\n timeout,\n focus: () => popup.focus(),\n cleanup: () => popup.close(),\n }\n void this.authorizationUrl(options, state, verifier)\n .then((url) => popup.location.replace(url))\n .catch((error) => {\n const attempt = this.finishAttempt()\n popup.close()\n attempt?.reject(error instanceof Error ? error : new Error(String(error)))\n })\n })\n }\n\n private async openModal(options: AuthLaunchOptions): Promise<AuthResult> {\n if (this.attempt) return this.joinAttempt(this.attempt)\n\n const { width, height, timeoutMs, readyTimeoutMs } = this.config.modal\n const previousFocus =\n document.activeElement instanceof HTMLElement ? document.activeElement : null\n const dialog = document.createElement('dialog')\n const header = document.createElement('div')\n const title = document.createElement('span')\n const close = document.createElement('button')\n const iframe = document.createElement('iframe')\n\n dialog.setAttribute('aria-label', 'POFSIS authentication')\n dialog.dataset.pofsisAuthModal = ''\n Object.assign(dialog.style, {\n width: `min(${width}px, calc(100vw - 32px))`,\n height: `min(${height}px, calc(100dvh - 32px))`,\n maxWidth: 'none',\n maxHeight: 'none',\n padding: '0',\n border: '0',\n borderRadius: '12px',\n boxShadow: '0 24px 80px rgba(0, 0, 0, 0.28)',\n overflow: 'hidden',\n })\n Object.assign(header.style, {\n height: '48px',\n padding: '0 10px 0 16px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n background: '#fff',\n borderBottom: '1px solid rgba(0, 0, 0, 0.10)',\n font: '500 14px/20px Inter, sans-serif',\n })\n title.textContent =\n options.screen === 'signup'\n ? 'Create account'\n : options.screen === 'reset'\n ? 'Reset password'\n : 'Sign in'\n close.type = 'button'\n close.setAttribute('aria-label', 'Close authentication')\n close.textContent = '\\u00d7'\n Object.assign(close.style, {\n width: '36px',\n height: '36px',\n padding: '0',\n border: '0',\n borderRadius: '8px',\n background: 'transparent',\n color: '#0a0a0a',\n cursor: 'pointer',\n font: '400 26px/36px sans-serif',\n })\n iframe.title = title.textContent\n iframe.setAttribute(\n 'sandbox',\n 'allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox',\n )\n iframe.setAttribute('allow', 'publickey-credentials-get *; publickey-credentials-create *')\n Object.assign(iframe.style, {\n display: 'block',\n width: '100%',\n height: 'calc(100% - 48px)',\n border: '0',\n background: '#fff',\n })\n header.append(title, close)\n dialog.append(header, iframe)\n document.body.append(dialog)\n\n const styleId = 'pofsis-auth-modal-style'\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style')\n style.id = styleId\n style.textContent =\n '[data-pofsis-auth-modal]::backdrop{background:rgba(10,10,10,.56);backdrop-filter:blur(2px)}'\n document.head.append(style)\n }\n\n const correlationId = randomValue()\n const state = `${correlationId}.${randomValue()}`\n const verifier = randomValue()\n const returnUrl = safeLocalPath(options.returnUrl)\n\n return new Promise<AuthResult>((resolve, reject) => {\n let attempt: AuthAttempt\n const cancel = () => {\n if (this.attempt !== attempt) return\n this.finishAttempt()?.resolve({ status: 'cancelled' })\n }\n close.addEventListener('click', cancel)\n dialog.addEventListener('cancel', (event) => {\n event.preventDefault()\n cancel()\n })\n dialog.addEventListener('click', (event) => {\n if (event.target !== dialog) return\n const rect = dialog.getBoundingClientRect()\n if (\n event.clientX < rect.left ||\n event.clientX > rect.right ||\n event.clientY < rect.top ||\n event.clientY > rect.bottom\n )\n cancel()\n })\n\n const timeout = setTimeout(() => {\n const completed = this.finishAttempt()\n completed?.reject(new Error('POFSIS Auth modal timed out.'))\n }, timeoutMs)\n const source = iframe.contentWindow\n if (!source) {\n dialog.remove()\n clearTimeout(timeout)\n reject(new Error('POFSIS Auth modal could not be created.'))\n return\n }\n attempt = {\n presentation: 'modal',\n source,\n state,\n verifier,\n correlationId,\n returnUrl,\n resolve,\n reject,\n timeout,\n focus: () => close.focus(),\n cleanup: () => {\n dialog.remove()\n previousFocus?.focus()\n },\n }\n this.attempt = attempt\n dialog.showModal()\n close.focus()\n\n void this.authorizationUrl(options, state, verifier)\n .then((url) => {\n if (this.attempt !== attempt) return\n const authOrigin = new URL(url).origin\n attempt.authOrigin = authOrigin\n const initMessage: ModalProtocolMessage = {\n type: MODAL_INIT_MESSAGE_TYPE,\n state,\n correlationId,\n applicationId: this.config.applicationId,\n }\n const sendInit = () =>\n iframe.contentWindow?.postMessage(initMessage, authOrigin)\n iframe.addEventListener('load', sendInit)\n iframe.src = url\n sendInit()\n attempt.timer = setInterval(sendInit, 250)\n attempt.readyTimeout = setTimeout(() => {\n const completed = this.finishAttempt()\n completed?.reject(new Error('POFSIS Auth modal could not be embedded.'))\n }, readyTimeoutMs)\n })\n .catch((error) => {\n const completed = this.finishAttempt()\n completed?.reject(error instanceof Error ? error : new Error(String(error)))\n })\n })\n }\n\n private joinAttempt(attempt: AuthAttempt) {\n attempt.focus()\n return new Promise<AuthResult>((resolve, reject) => {\n const originalResolve = attempt.resolve\n const originalReject = attempt.reject\n attempt.resolve = (value) => {\n originalResolve(value)\n resolve(value)\n }\n attempt.reject = (error) => {\n originalReject(error)\n reject(error)\n }\n })\n }\n\n private finishAttempt() {\n const attempt = this.attempt\n if (!attempt) return null\n if (attempt.timer) clearInterval(attempt.timer)\n clearTimeout(attempt.timeout)\n if (attempt.readyTimeout) clearTimeout(attempt.readyTimeout)\n this.attempt = null\n attempt.cleanup()\n return attempt\n }\n\n private onPopupMessage = (event: MessageEvent<PopupCallbackMessage | ModalProtocolMessage>) => {\n const attempt = this.attempt\n const message = event.data\n if (\n attempt?.presentation === 'modal' &&\n message?.type === MODAL_READY_MESSAGE_TYPE &&\n event.origin === attempt.authOrigin &&\n event.source === attempt.source &&\n message.applicationId === this.config.applicationId &&\n message.correlationId === attempt.correlationId &&\n message.state === attempt.state\n ) {\n attempt.ready = true\n if (attempt.timer) clearInterval(attempt.timer)\n if (attempt.readyTimeout) clearTimeout(attempt.readyTimeout)\n attempt.timer = undefined\n attempt.readyTimeout = undefined\n return\n }\n if (\n !attempt ||\n (attempt.presentation === 'modal' && !attempt.ready) ||\n event.origin !== window.location.origin ||\n event.source !== attempt.source ||\n message?.type !== POPUP_MESSAGE_TYPE ||\n message.correlationId !== attempt.correlationId ||\n correlationFromState(message.state || null) !== attempt.correlationId ||\n message.state !== attempt.state\n )\n return\n\n const completed = this.finishAttempt()\n if (!completed) return\n if (message.error || !message.code) {\n completed.reject(new Error(message.error || 'POFSIS Auth callback was incomplete.'))\n return\n }\n void this.completeCode(message.code, message.state, completed.verifier)\n .then(() => {\n if (completed.returnUrl) window.history.replaceState(null, '', completed.returnUrl)\n completed.resolve({ status: 'authenticated', user: this.getUser()! })\n })\n .catch((error) => {\n completed.reject(error instanceof Error ? error : new Error(String(error)))\n })\n }\n\n private async completeCode(code: string, state: string, verifier: string) {\n if (!state || !verifier) throw new Error('Authentication state could not be verified.')\n const client = await this.loadClient()\n this.accept(await exchangeCode(this.config, code, verifier, client))\n }\n\n async completeRedirectCallback(code: string, state: string) {\n const expected = sessionStorage.getItem(this.storageKey('state'))\n const verifier = sessionStorage.getItem(this.storageKey('verifier'))\n sessionStorage.removeItem(this.storageKey('state'))\n sessionStorage.removeItem(this.storageKey('verifier'))\n if (!expected || !verifier || state !== expected) {\n throw new Error('Authentication state could not be verified.')\n }\n await this.completeCode(code, state, verifier)\n }\n}\n\nexport function createPofsisAuth(config: PofsisAuthClientConfig) {\n return new PofsisAuthClient(config)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
async function e(e){if(e.status===204)return null;let t=await e.text();return t?JSON.parse(t):null}async function t(t,n,r){let i=await fetch(`${t.apiBaseUrl}${n}`,{credentials:`include`,...r,headers:{Accept:`application/json`,...r?.body&&!(r.body instanceof FormData)?{"Content-Type":`application/json`}:{},...r?.headers}});if(!i.ok){let e=Error(`Auth API ${n} failed (${i.status})`);throw e.status=i.status,e}return{status:i.status,data:await e(i)}}async function n(e){let{data:n}=await t(e,`/oauth/applications/${encodeURIComponent(e.applicationId)}/client?origin=${encodeURIComponent(window.location.origin)}`);return n}async function r(e,n,r,i){let{data:a}=await t(e,`/oauth/token`,{method:`POST`,body:JSON.stringify({grant_type:`authorization_code`,client_id:i.client_id,redirect_uri:i.redirect_uri,code:n,code_verifier:r})});return a}async function i(e,n){let{data:r}=await t(e,`/oauth/token`,{method:`POST`,body:JSON.stringify({grant_type:`refresh_token`,client_id:n})});return r||null}async function a(e){try{return await t(e,`/auth/session`),!0}catch{return!1}}async function o(e){await t(e,`/auth/logout`,{method:`POST`})}async function s(e,n){let{data:r}=await t(e,`/auth/profile/me`,{headers:{Authorization:`Bearer ${n}`}});return r}async function c(e,n,r){let{data:i}=await t(e,`/auth/profile/me`,{method:`PATCH`,headers:{Authorization:`Bearer ${n}`},body:JSON.stringify(r)});return i}async function l(e,n,r,i){let a=new FormData;a.append(`file`,i);let{data:o}=await t(e,`/auth/profile/me/images/${r}`,{method:`POST`,headers:{Authorization:`Bearer ${n}`},body:a});return o}async function u(e,n,r){let{data:i}=await t(e,`/auth/profile/me/images/${r}`,{method:`DELETE`,headers:{Authorization:`Bearer ${n}`}});return i}function d(e){return e.replace(/\/$/,``)}function f(e={}){let t=e.applicationId?.trim(),n=e.apiBaseUrl?.trim(),r=e.authUrl?.trim(),i=e.scope?.trim()||`openid profile email`,a=e.callbackPath?.trim()||`/auth/callback`,o={width:e.popup?.width??480,height:e.popup?.height??720,name:e.popup?.name?.trim()||`pofsis-auth`,timeoutMs:e.popup?.timeoutMs??3e5},s={width:e.modal?.width??480,height:e.modal?.height??720,timeoutMs:e.modal?.timeoutMs??3e5,readyTimeoutMs:e.modal?.readyTimeoutMs??15e3},c=[];if(t||c.push(`applicationId`),n||c.push(`apiBaseUrl`),r||c.push(`authUrl`),c.length)throw Error(`@pofsis-nbt/pofsis-auth missing config: ${c.join(`, `)}`);if(!t||!n||!r)throw Error(`@pofsis-nbt/pofsis-auth missing config`);if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t))throw Error(`@pofsis-nbt/pofsis-auth applicationId must be a UUID`);if(!a.startsWith(`/`)||a.startsWith(`//`))throw Error(`@pofsis-nbt/pofsis-auth callbackPath must be application-relative`);if(o.width<=0||o.height<=0||o.timeoutMs<=0)throw Error(`@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive`);if(s.width<=0||s.height<=0||s.timeoutMs<=0||s.readyTimeoutMs<=0)throw Error(`@pofsis-nbt/pofsis-auth modal dimensions and timeouts must be positive`);return{applicationId:t.toLowerCase(),apiBaseUrl:d(n),authUrl:d(r),scope:i,callbackPath:a,popup:o,modal:s}}var p=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,m=/^(?:\+63|63|0)?9\d{9}$/,h=new Set([`password`,`passkey`,`otp`]),g=new Set([`login`,`signup`,`reset`]),_=320;function v(e,t=!1){let n=typeof e==`string`?e.trim():``;if(!n||n.length>_)return;if(p.test(n))return n.toLowerCase();let r=n.replace(/[\s()-]/g,``);if(!t&&m.test(r))return`+63${r.replace(/^(?:\+63|63|0)/,``)}`}function y(e,t=`login`){let n=typeof e==`string`?{returnUrl:e}:e||{},r=n.screen===`register`?`signup`:n.screen,i=g.has(r)?r:t,a=h.has(n.method)?n.method:void 0,o=i===`login`||i===`signup`&&(a===`password`||a===`otp`)?a:void 0;return{returnUrl:n.returnUrl,screen:i,loginHint:v(n.loginHint),method:o}}function b(e){let t=new URLSearchParams(e),n=t.get(`login_hint`),r=n===null?v(t.get(`email`),!0):v(n);return y({screen:t.get(`screen`)||void 0,loginHint:r,method:t.get(`method`)||void 0})}function x({authUrl:e,query:t,options:n}){let r=y(n),i=new URL(e);if(i.search=t.toString(),n?.presentation===`modal`&&i.searchParams.set(`presentation`,`modal`),r.loginHint&&i.searchParams.set(`login_hint`,r.loginHint),r.screen===`login`&&r.method&&i.searchParams.set(`method`,r.method),r.screen===`login`)return i.toString();let a=r.screen===`signup`?`/signup`:`/forgot-password`,o=new URL(a,i),s=t.get(`client_id`);return s&&o.searchParams.set(`client_id`,s),n?.presentation===`modal`&&o.searchParams.set(`presentation`,`modal`),o.searchParams.set(`return_to`,`${i.pathname}${i.search}`),r.loginHint&&o.searchParams.set(`login_hint`,r.loginHint),r.screen===`signup`&&o.searchParams.set(`method`,r.method||`password`),o.toString()}var S=`pofsis-auth:callback`,C=`pofsis-auth:frame-init`;function w(e){if(!e)return;let t=e.indexOf(`.`);return t>0?e.slice(0,t):void 0}function T(e=window.location.origin){let t=new URLSearchParams(window.location.search),n=t.get(`state`)||void 0,r=w(n||null);if(!r)return!1;let i=window.opener&&!window.opener.closed?window.opener:null,a=window.parent===window?null:window.parent,o=i||a;if(!o)return!1;let s={type:S,code:t.get(`code`)||void 0,state:n,error:t.get(`error`)||void 0,correlationId:r};return o.postMessage(s,e),i&&window.close(),!0}var E=T,D=e=>btoa(String.fromCharCode(...e)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``),O=()=>D(crypto.getRandomValues(new Uint8Array(32)));async function k(e){return D(new Uint8Array(await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e))))}var A=e=>e?.startsWith(`/`)&&!e.startsWith(`//`)?e:void 0,j=e=>({token_type:e.token_type,expires_in:e.expires_in,user:e.user}),M=class{config;token=null;session=null;client=null;clientPromise=null;refreshPromise=null;subscribers=new Set;attempt=null;listening=!1;constructor(e){this.config=f(e),this.attach()}attach(){this.listening||=(window.addEventListener(`message`,this.onPopupMessage),!0)}destroy(){window.removeEventListener(`message`,this.onPopupMessage),this.listening=!1;let e=this.finishAttempt();e&&e.resolve({status:`cancelled`}),this.subscribers.clear()}getUser(){return this.session?.user??null}getSession(){return this.session}getAccessToken(){return this.token}subscribe(e){return this.attach(),this.subscribers.add(e),e(this.session),()=>{this.subscribers.delete(e)}}emit(){for(let e of this.subscribers)e(this.session)}accept(e){this.token=e.access_token,this.session=j(e),this.emit()}loadClient(){return this.clientPromise||=n(this.config).then(e=>this.client=e).catch(e=>{throw this.clientPromise=null,e}),this.clientPromise}getOAuthClient(){return this.loadClient()}async refreshSession(){let e=await this.loadClient();return this.refreshPromise||=i(this.config,e.client_id).then(e=>{e?this.accept(e):this.clearSession()}).finally(()=>this.refreshPromise=null),this.refreshPromise}async isRemoteSessionActive(){return a(this.config)}clearSession(){this.token=null,this.session=null,this.emit()}replaceUser(e){this.session&&(this.session={...this.session,user:e},this.emit())}async logout(){try{await o(this.config)}finally{this.clearSession()}}signup(e={}){return this.login({...e,screen:`signup`})}resetPassword(e={}){return this.login({...e,screen:`reset`})}async login(e={}){let t=y(e),n=e.presentation??`popup`;return n===`popup`?this.openPopup({...e,...t}):n===`modal`?this.openModal({...e,...t}):this.startRedirect({...e,...t})}async authorizationUrl(e,t,n){let r=await this.loadClient(),i=new URLSearchParams({client_id:r.client_id,redirect_uri:r.redirect_uri,response_type:`code`,scope:this.config.scope,state:t,code_challenge:await k(n),code_challenge_method:`S256`});return x({authUrl:this.config.authUrl,query:i,options:e})}storageKey(e){return`${this.config.applicationId}.auth.${e}`}async startRedirect(e){let t=O(),n=O();sessionStorage.setItem(this.storageKey(`state`),t),sessionStorage.setItem(this.storageKey(`verifier`),n);let r=A(e.returnUrl);return r?sessionStorage.setItem(this.storageKey(`return-path`),r):sessionStorage.removeItem(this.storageKey(`return-path`)),window.location.assign(await this.authorizationUrl(e,t,n)),{status:`redirecting`}}async openPopup(e){if(this.attempt)return this.joinAttempt(this.attempt);let{width:t,height:n,name:r,timeoutMs:i}=this.config.popup,a=Math.max(0,window.screenX+(window.outerWidth-t)/2),o=Math.max(0,window.screenY+(window.outerHeight-n)/2),s=window.open(`about:blank`,r,`popup=yes,width=${t},height=${n},left=${Math.round(a)},top=${Math.round(o)}`);if(!s)return this.startRedirect({...e,presentation:`redirect`});let c=O(),l=`${c}.${O()}`,u=O(),d=A(e.returnUrl);return new Promise((t,n)=>{let r=setInterval(()=>{s.closed&&this.finishAttempt()?.resolve({status:`cancelled`})},250),a=setTimeout(()=>{let e=this.finishAttempt();s.close(),e?.reject(Error(`POFSIS Auth popup timed out.`))},i);this.attempt={presentation:`popup`,source:s,state:l,verifier:u,correlationId:c,returnUrl:d,resolve:t,reject:n,timer:r,timeout:a,focus:()=>s.focus(),cleanup:()=>s.close()},this.authorizationUrl(e,l,u).then(e=>s.location.replace(e)).catch(e=>{let t=this.finishAttempt();s.close(),t?.reject(e instanceof Error?e:Error(String(e)))})})}async openModal(e){if(this.attempt)return this.joinAttempt(this.attempt);let{width:t,height:n,timeoutMs:r,readyTimeoutMs:i}=this.config.modal,a=document.activeElement instanceof HTMLElement?document.activeElement:null,o=document.createElement(`dialog`),s=document.createElement(`div`),c=document.createElement(`span`),l=document.createElement(`button`),u=document.createElement(`iframe`);o.setAttribute(`aria-label`,`POFSIS authentication`),o.dataset.pofsisAuthModal=``,Object.assign(o.style,{width:`min(${t}px, calc(100vw - 32px))`,height:`min(${n}px, calc(100dvh - 32px))`,maxWidth:`none`,maxHeight:`none`,padding:`0`,border:`0`,borderRadius:`12px`,boxShadow:`0 24px 80px rgba(0, 0, 0, 0.28)`,overflow:`hidden`}),Object.assign(s.style,{height:`48px`,padding:`0 10px 0 16px`,display:`flex`,alignItems:`center`,justifyContent:`space-between`,background:`#fff`,borderBottom:`1px solid rgba(0, 0, 0, 0.10)`,font:`500 14px/20px Inter, sans-serif`}),c.textContent=e.screen===`signup`?`Create account`:e.screen===`reset`?`Reset password`:`Sign in`,l.type=`button`,l.setAttribute(`aria-label`,`Close authentication`),l.textContent=`×`,Object.assign(l.style,{width:`36px`,height:`36px`,padding:`0`,border:`0`,borderRadius:`8px`,background:`transparent`,color:`#0a0a0a`,cursor:`pointer`,font:`400 26px/36px sans-serif`}),u.title=c.textContent,u.setAttribute(`sandbox`,`allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox`),u.setAttribute(`allow`,`publickey-credentials-get *; publickey-credentials-create *`),Object.assign(u.style,{display:`block`,width:`100%`,height:`calc(100% - 48px)`,border:`0`,background:`#fff`}),s.append(c,l),o.append(s,u),document.body.append(o);let d=`pofsis-auth-modal-style`;if(!document.getElementById(d)){let e=document.createElement(`style`);e.id=d,e.textContent=`[data-pofsis-auth-modal]::backdrop{background:rgba(10,10,10,.56);backdrop-filter:blur(2px)}`,document.head.append(e)}let f=O(),p=`${f}.${O()}`,m=O(),h=A(e.returnUrl);return new Promise((t,n)=>{let s,c=()=>{this.attempt===s&&this.finishAttempt()?.resolve({status:`cancelled`})};l.addEventListener(`click`,c),o.addEventListener(`cancel`,e=>{e.preventDefault(),c()}),o.addEventListener(`click`,e=>{if(e.target!==o)return;let t=o.getBoundingClientRect();(e.clientX<t.left||e.clientX>t.right||e.clientY<t.top||e.clientY>t.bottom)&&c()});let d=setTimeout(()=>{this.finishAttempt()?.reject(Error(`POFSIS Auth modal timed out.`))},r),g=u.contentWindow;if(!g){o.remove(),clearTimeout(d),n(Error(`POFSIS Auth modal could not be created.`));return}s={presentation:`modal`,source:g,state:p,verifier:m,correlationId:f,returnUrl:h,resolve:t,reject:n,timeout:d,focus:()=>l.focus(),cleanup:()=>{o.remove(),a?.focus()}},this.attempt=s,o.showModal(),l.focus(),this.authorizationUrl(e,p,m).then(e=>{if(this.attempt!==s)return;let t=new URL(e).origin;s.authOrigin=t;let n={type:C,state:p,correlationId:f,applicationId:this.config.applicationId},r=()=>u.contentWindow?.postMessage(n,t);u.addEventListener(`load`,r),u.src=e,r(),s.timer=setInterval(r,250),s.readyTimeout=setTimeout(()=>{this.finishAttempt()?.reject(Error(`POFSIS Auth modal could not be embedded.`))},i)}).catch(e=>{this.finishAttempt()?.reject(e instanceof Error?e:Error(String(e)))})})}joinAttempt(e){return e.focus(),new Promise((t,n)=>{let r=e.resolve,i=e.reject;e.resolve=e=>{r(e),t(e)},e.reject=e=>{i(e),n(e)}})}finishAttempt(){let e=this.attempt;return e?(e.timer&&clearInterval(e.timer),clearTimeout(e.timeout),e.readyTimeout&&clearTimeout(e.readyTimeout),this.attempt=null,e.cleanup(),e):null}onPopupMessage=e=>{let t=this.attempt,n=e.data;if(t?.presentation===`modal`&&n?.type===`pofsis-auth:frame-ready`&&e.origin===t.authOrigin&&e.source===t.source&&n.applicationId===this.config.applicationId&&n.correlationId===t.correlationId&&n.state===t.state){t.ready=!0,t.timer&&clearInterval(t.timer),t.readyTimeout&&clearTimeout(t.readyTimeout),t.timer=void 0,t.readyTimeout=void 0;return}if(!t||t.presentation===`modal`&&!t.ready||e.origin!==window.location.origin||e.source!==t.source||n?.type!==`pofsis-auth:callback`||n.correlationId!==t.correlationId||w(n.state||null)!==t.correlationId||n.state!==t.state)return;let r=this.finishAttempt();if(r){if(n.error||!n.code){r.reject(Error(n.error||`POFSIS Auth callback was incomplete.`));return}this.completeCode(n.code,n.state,r.verifier).then(()=>{r.returnUrl&&window.history.replaceState(null,``,r.returnUrl),r.resolve({status:`authenticated`,user:this.getUser()})}).catch(e=>{r.reject(e instanceof Error?e:Error(String(e)))})}};async completeCode(e,t,n){if(!t||!n)throw Error(`Authentication state could not be verified.`);let i=await this.loadClient();this.accept(await r(this.config,e,n,i))}async completeRedirectCallback(e,t){let n=sessionStorage.getItem(this.storageKey(`state`)),r=sessionStorage.getItem(this.storageKey(`verifier`));if(sessionStorage.removeItem(this.storageKey(`state`)),sessionStorage.removeItem(this.storageKey(`verifier`)),!n||!r||t!==n)throw Error(`Authentication state could not be verified.`);await this.completeCode(e,t,r)}};function N(e){return new M(e)}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return l}});
|
|
2
|
+
//# sourceMappingURL=PofsisAuthClient-c4lzLzjV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PofsisAuthClient-c4lzLzjV.cjs","names":[],"sources":["../src/auth/api.ts","../src/auth/config.ts","../src/auth/authLaunch.ts","../src/core/popupProtocol.ts","../src/auth/pkce.ts","../src/core/PofsisAuthClient.ts"],"sourcesContent":["import type { AccountProfile, OAuthClientConfig, PofsisAuthConfig, TokenResponse } from '../types'\r\n\r\nasync function parseJson<T>(response: Response): Promise<T> {\r\n if (response.status === 204) return null as T\r\n const text = await response.text()\r\n if (!text) return null as T\r\n return JSON.parse(text) as T\r\n}\r\n\r\nasync function request<T>(\r\n config: PofsisAuthConfig,\r\n path: string,\r\n init?: RequestInit,\r\n): Promise<{ status: number; data: T }> {\r\n const response = await fetch(`${config.apiBaseUrl}${path}`, {\r\n credentials: 'include',\r\n ...init,\r\n headers: {\r\n Accept: 'application/json',\r\n ...(init?.body && !(init.body instanceof FormData)\r\n ? { 'Content-Type': 'application/json' }\r\n : {}),\r\n ...init?.headers,\r\n },\r\n })\r\n if (!response.ok) {\r\n const error = new Error(`Auth API ${path} failed (${response.status})`)\r\n ;(error as Error & { status?: number }).status = response.status\r\n throw error\r\n }\r\n return { status: response.status, data: await parseJson<T>(response) }\r\n}\r\n\r\nexport async function fetchOAuthClient(config: PofsisAuthConfig) {\r\n const applicationId = encodeURIComponent(config.applicationId)\r\n const origin = encodeURIComponent(window.location.origin)\r\n const { data } = await request<OAuthClientConfig>(\r\n config,\r\n `/oauth/applications/${applicationId}/client?origin=${origin}`,\r\n )\r\n return data\r\n}\r\n\r\nexport async function exchangeCode(\r\n config: PofsisAuthConfig,\r\n code: string,\r\n verifier: string,\r\n client: Pick<OAuthClientConfig, 'client_id' | 'redirect_uri'>,\r\n) {\r\n const { data } = await request<TokenResponse>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'authorization_code',\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n code,\r\n code_verifier: verifier,\r\n }),\r\n })\r\n return data\r\n}\r\n\r\nexport async function refresh(config: PofsisAuthConfig, clientId: string) {\r\n const { data } = await request<TokenResponse | null>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n client_id: clientId,\r\n }),\r\n })\r\n return data || null\r\n}\r\n\r\nexport async function checkSession(config: PofsisAuthConfig) {\r\n try {\r\n await request(config, '/auth/session')\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nexport async function signOut(config: PofsisAuthConfig) {\r\n await request(config, '/auth/logout', { method: 'POST' })\r\n}\r\n\r\nexport async function getAccountProfile(config: PofsisAuthConfig, accessToken: string) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n\r\nexport async function updateAccountProfile(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n profile: { firstName?: string | null; lastName?: string | null },\r\n) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n method: 'PATCH',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body: JSON.stringify(profile),\r\n })\r\n return data\r\n}\r\n\r\nexport async function uploadAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n file: File,\r\n) {\r\n const body = new FormData()\r\n body.append('file', file)\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'POST',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body,\r\n })\r\n return data\r\n}\r\n\r\nexport async function deleteAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n) {\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'DELETE',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n","import type { PofsisAuthClientConfig, ResolvedPofsisAuthConfig } from '../types'\n\nfunction stripTrailingSlash(value: string) {\n return value.replace(/\\/$/, '')\n}\n\nexport type ConfigOverrides = Partial<PofsisAuthClientConfig>\n\n/**\n * Validate and normalize explicitly supplied runtime configuration.\n */\nexport function resolveConfig(overrides: ConfigOverrides = {}): ResolvedPofsisAuthConfig {\n const applicationId = overrides.applicationId?.trim()\n const apiBaseUrl = overrides.apiBaseUrl?.trim()\n const authUrl = overrides.authUrl?.trim()\n const scope = overrides.scope?.trim() || 'openid profile email'\n const callbackPath = overrides.callbackPath?.trim() || '/auth/callback'\n const popup = {\n width: overrides.popup?.width ?? 480,\n height: overrides.popup?.height ?? 720,\n name: overrides.popup?.name?.trim() || 'pofsis-auth',\n timeoutMs: overrides.popup?.timeoutMs ?? 300_000,\n }\n const modal = {\n width: overrides.modal?.width ?? 480,\n height: overrides.modal?.height ?? 720,\n timeoutMs: overrides.modal?.timeoutMs ?? 300_000,\n readyTimeoutMs: overrides.modal?.readyTimeoutMs ?? 15_000,\n }\n\n const missing: string[] = []\n if (!applicationId) missing.push('applicationId')\n if (!apiBaseUrl) missing.push('apiBaseUrl')\n if (!authUrl) missing.push('authUrl')\n if (missing.length) {\n throw new Error(`@pofsis-nbt/pofsis-auth missing config: ${missing.join(', ')}`)\n }\n if (!applicationId || !apiBaseUrl || !authUrl) {\n throw new Error('@pofsis-nbt/pofsis-auth missing config')\n }\n if (\n !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n applicationId,\n )\n ) {\n throw new Error('@pofsis-nbt/pofsis-auth applicationId must be a UUID')\n }\n if (!callbackPath.startsWith('/') || callbackPath.startsWith('//')) {\n throw new Error('@pofsis-nbt/pofsis-auth callbackPath must be application-relative')\n }\n if (popup.width <= 0 || popup.height <= 0 || popup.timeoutMs <= 0) {\n throw new Error('@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive')\n }\n if (\n modal.width <= 0 ||\n modal.height <= 0 ||\n modal.timeoutMs <= 0 ||\n modal.readyTimeoutMs <= 0\n ) {\n throw new Error('@pofsis-nbt/pofsis-auth modal dimensions and timeouts must be positive')\n }\n\n return {\n applicationId: applicationId.toLowerCase(),\n apiBaseUrl: stripTrailingSlash(apiBaseUrl),\n authUrl: stripTrailingSlash(authUrl),\n scope,\n callbackPath,\n popup,\n modal,\n }\n}\n","import type { AuthLaunchOptions, AuthMethod, AuthScreen } from '../types'\n\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst PHILIPPINE_MOBILE = /^(?:\\+63|63|0)?9\\d{9}$/\nconst METHODS = new Set<AuthMethod>(['password', 'passkey', 'otp'])\nconst SCREENS = new Set<AuthScreen>(['login', 'signup', 'reset'])\nconst MAX_HINT_LENGTH = 320\n\nfunction normalizeHint(value: unknown, emailOnly = false): string | undefined {\n const candidate = typeof value === 'string' ? value.trim() : ''\n if (!candidate || candidate.length > MAX_HINT_LENGTH) return undefined\n if (EMAIL.test(candidate)) return candidate.toLowerCase()\n const compact = candidate.replace(/[\\s()-]/g, '')\n if (emailOnly || !PHILIPPINE_MOBILE.test(compact)) return undefined\n return `+63${compact.replace(/^(?:\\+63|63|0)/, '')}`\n}\n\nexport function normalizeAuthLaunchOptions(\n value?: AuthLaunchOptions | string | null,\n defaultScreen: AuthScreen = 'login',\n) {\n const options = typeof value === 'string' ? { returnUrl: value } : value || {}\n const requestedScreen = options.screen === 'register' ? 'signup' : options.screen\n const screen = SCREENS.has(requestedScreen as AuthScreen)\n ? (requestedScreen as AuthScreen)\n : defaultScreen\n const requestedMethod = METHODS.has(options.method as AuthMethod)\n ? (options.method as AuthMethod)\n : undefined\n const method =\n screen === 'login' ||\n (screen === 'signup' && (requestedMethod === 'password' || requestedMethod === 'otp'))\n ? requestedMethod\n : undefined\n return {\n returnUrl: options.returnUrl,\n screen,\n loginHint: normalizeHint(options.loginHint),\n method,\n }\n}\n\nexport function authLaunchOptionsFromSearch(search: string) {\n const params = new URLSearchParams(search)\n const canonicalHint = params.get('login_hint')\n const loginHint =\n canonicalHint !== null\n ? normalizeHint(canonicalHint)\n : normalizeHint(params.get('email'), true)\n return normalizeAuthLaunchOptions({\n screen: (params.get('screen') || undefined) as AuthLaunchOptions['screen'],\n loginHint,\n method: (params.get('method') || undefined) as AuthLaunchOptions['method'],\n })\n}\n\nexport function buildAuthDestination({\n authUrl,\n query,\n options,\n}: {\n authUrl: string\n query: URLSearchParams\n options?: AuthLaunchOptions\n}) {\n const launch = normalizeAuthLaunchOptions(options)\n const authorizationUrl = new URL(authUrl)\n authorizationUrl.search = query.toString()\n if (options?.presentation === 'modal') {\n authorizationUrl.searchParams.set('presentation', 'modal')\n }\n if (launch.loginHint) authorizationUrl.searchParams.set('login_hint', launch.loginHint)\n if (launch.screen === 'login' && launch.method) {\n authorizationUrl.searchParams.set('method', launch.method)\n }\n if (launch.screen === 'login') return authorizationUrl.toString()\n\n const pathname = launch.screen === 'signup' ? '/signup' : '/forgot-password'\n const destination = new URL(pathname, authorizationUrl)\n const clientId = query.get('client_id')\n if (clientId) destination.searchParams.set('client_id', clientId)\n if (options?.presentation === 'modal') destination.searchParams.set('presentation', 'modal')\n destination.searchParams.set(\n 'return_to',\n `${authorizationUrl.pathname}${authorizationUrl.search}`,\n )\n if (launch.loginHint) destination.searchParams.set('login_hint', launch.loginHint)\n if (launch.screen === 'signup') {\n destination.searchParams.set('method', launch.method || 'password')\n }\n return destination.toString()\n}\n","export const POPUP_MESSAGE_TYPE = 'pofsis-auth:callback'\nexport const MODAL_INIT_MESSAGE_TYPE = 'pofsis-auth:frame-init'\nexport const MODAL_READY_MESSAGE_TYPE = 'pofsis-auth:frame-ready'\n\nexport type PopupCallbackMessage = {\n type: typeof POPUP_MESSAGE_TYPE\n code?: string\n state?: string\n error?: string\n correlationId?: string\n}\n\nexport type ModalProtocolMessage = {\n type: typeof MODAL_INIT_MESSAGE_TYPE | typeof MODAL_READY_MESSAGE_TYPE\n state: string\n correlationId: string\n applicationId: string\n}\n\nexport function correlationFromState(state: string | null) {\n if (!state) return undefined\n const separator = state.indexOf('.')\n return separator > 0 ? state.slice(0, separator) : undefined\n}\n\nexport function relayAuthCallback(targetOrigin = window.location.origin) {\n const params = new URLSearchParams(window.location.search)\n const state = params.get('state') || undefined\n const correlationId = correlationFromState(state || null)\n if (!correlationId) return false\n const opener = window.opener && !window.opener.closed ? window.opener : null\n const parent = window.parent !== window ? window.parent : null\n const recipient = opener || parent\n if (!recipient) return false\n const message: PopupCallbackMessage = {\n type: POPUP_MESSAGE_TYPE,\n code: params.get('code') || undefined,\n state,\n error: params.get('error') || undefined,\n correlationId,\n }\n recipient.postMessage(message, targetOrigin)\n if (opener) window.close()\n return true\n}\n\n/** @deprecated Use relayAuthCallback for both popup and modal callbacks. */\nexport const relayPopupCallback = relayAuthCallback\n","const encode = (bytes: Uint8Array) =>\r\n btoa(String.fromCharCode(...bytes))\r\n .replace(/\\+/g, '-')\r\n .replace(/\\//g, '_')\r\n .replace(/=+$/, '')\r\n\r\nexport const randomValue = () => encode(crypto.getRandomValues(new Uint8Array(32)))\r\n\r\nexport async function pkceChallenge(verifier: string) {\r\n return encode(\r\n new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))),\r\n )\r\n}\r\n","import { checkSession, exchangeCode, fetchOAuthClient, refresh, signOut } from '../auth/api'\nimport { buildAuthDestination, normalizeAuthLaunchOptions } from '../auth/authLaunch'\nimport { resolveConfig } from '../auth/config'\nimport { pkceChallenge, randomValue } from '../auth/pkce'\nimport type {\n AuthLaunchOptions,\n AuthResult,\n OAuthClientConfig,\n PofsisAuthClientConfig,\n ResolvedPofsisAuthConfig,\n PofsisUser,\n SessionPayload,\n} from '../types'\nimport {\n correlationFromState,\n MODAL_INIT_MESSAGE_TYPE,\n MODAL_READY_MESSAGE_TYPE,\n POPUP_MESSAGE_TYPE,\n type ModalProtocolMessage,\n type PopupCallbackMessage,\n} from './popupProtocol'\n\ntype Subscriber = (session: SessionPayload | null) => void\ntype AuthAttempt = {\n presentation: 'popup' | 'modal'\n source: Window\n state: string\n verifier: string\n correlationId: string\n returnUrl?: string\n resolve: (result: AuthResult) => void\n reject: (error: Error) => void\n timer?: ReturnType<typeof setInterval>\n timeout: ReturnType<typeof setTimeout>\n readyTimeout?: ReturnType<typeof setTimeout>\n ready?: boolean\n authOrigin?: string\n focus: () => void\n cleanup: () => void\n}\n\nconst safeLocalPath = (value?: string) =>\n value?.startsWith('/') && !value.startsWith('//') ? value : undefined\n\nconst toSession = (result: { token_type: string; expires_in: number; user: PofsisUser }) => ({\n token_type: result.token_type,\n expires_in: result.expires_in,\n user: result.user,\n})\n\nexport class PofsisAuthClient {\n readonly config: ResolvedPofsisAuthConfig\n private token: string | null = null\n private session: SessionPayload | null = null\n private client: OAuthClientConfig | null = null\n private clientPromise: Promise<OAuthClientConfig> | null = null\n private refreshPromise: Promise<void> | null = null\n private subscribers = new Set<Subscriber>()\n private attempt: AuthAttempt | null = null\n private listening = false\n\n constructor(config: PofsisAuthClientConfig) {\n this.config = resolveConfig(config)\n this.attach()\n }\n\n private attach() {\n if (this.listening) return\n window.addEventListener('message', this.onPopupMessage)\n this.listening = true\n }\n\n destroy() {\n window.removeEventListener('message', this.onPopupMessage)\n this.listening = false\n const attempt = this.finishAttempt()\n if (attempt) {\n attempt.resolve({ status: 'cancelled' })\n }\n this.subscribers.clear()\n }\n\n getUser() {\n return this.session?.user ?? null\n }\n\n getSession() {\n return this.session\n }\n\n getAccessToken() {\n return this.token\n }\n\n subscribe(listener: Subscriber) {\n this.attach()\n this.subscribers.add(listener)\n listener(this.session)\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n private emit() {\n for (const listener of this.subscribers) listener(this.session)\n }\n\n private accept(result: Awaited<ReturnType<typeof exchangeCode>>) {\n this.token = result.access_token\n this.session = toSession(result)\n this.emit()\n }\n\n private loadClient() {\n if (!this.clientPromise) {\n this.clientPromise = fetchOAuthClient(this.config)\n .then((client) => (this.client = client))\n .catch((error) => {\n this.clientPromise = null\n throw error\n })\n }\n return this.clientPromise\n }\n\n getOAuthClient() {\n return this.loadClient()\n }\n\n async refreshSession() {\n const client = await this.loadClient()\n if (!this.refreshPromise) {\n this.refreshPromise = refresh(this.config, client.client_id)\n .then((result) => {\n if (result) this.accept(result)\n else this.clearSession()\n })\n .finally(() => (this.refreshPromise = null))\n }\n return this.refreshPromise\n }\n\n async isRemoteSessionActive() {\n return checkSession(this.config)\n }\n\n clearSession() {\n this.token = null\n this.session = null\n this.emit()\n }\n\n replaceUser(user: PofsisUser) {\n if (!this.session) return\n this.session = { ...this.session, user }\n this.emit()\n }\n\n async logout() {\n try {\n await signOut(this.config)\n } finally {\n this.clearSession()\n }\n }\n\n signup(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\n return this.login({ ...options, screen: 'signup' })\n }\n\n resetPassword(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\n return this.login({ ...options, screen: 'reset' })\n }\n\n async login(options: AuthLaunchOptions = {}): Promise<AuthResult> {\n const launch = normalizeAuthLaunchOptions(options)\n const presentation = options.presentation ?? 'popup'\n if (presentation === 'popup') return this.openPopup({ ...options, ...launch })\n if (presentation === 'modal') return this.openModal({ ...options, ...launch })\n return this.startRedirect({ ...options, ...launch })\n }\n\n private async authorizationUrl(options: AuthLaunchOptions, state: string, verifier: string) {\n const client = await this.loadClient()\n const query = new URLSearchParams({\n client_id: client.client_id,\n redirect_uri: client.redirect_uri,\n response_type: 'code',\n scope: this.config.scope,\n state,\n code_challenge: await pkceChallenge(verifier),\n code_challenge_method: 'S256',\n })\n return buildAuthDestination({\n authUrl: this.config.authUrl,\n query,\n options,\n })\n }\n\n private storageKey(suffix: string) {\n return `${this.config.applicationId}.auth.${suffix}`\n }\n\n private async startRedirect(options: AuthLaunchOptions): Promise<AuthResult> {\n const state = randomValue()\n const verifier = randomValue()\n sessionStorage.setItem(this.storageKey('state'), state)\n sessionStorage.setItem(this.storageKey('verifier'), verifier)\n const returnUrl = safeLocalPath(options.returnUrl)\n if (returnUrl) sessionStorage.setItem(this.storageKey('return-path'), returnUrl)\n else sessionStorage.removeItem(this.storageKey('return-path'))\n window.location.assign(await this.authorizationUrl(options, state, verifier))\n return { status: 'redirecting' }\n }\n\n private async openPopup(options: AuthLaunchOptions): Promise<AuthResult> {\n if (this.attempt) return this.joinAttempt(this.attempt)\n const { width, height, name, timeoutMs } = this.config.popup\n const left = Math.max(0, window.screenX + (window.outerWidth - width) / 2)\n const top = Math.max(0, window.screenY + (window.outerHeight - height) / 2)\n const popup = window.open(\n 'about:blank',\n name,\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\n )\n if (!popup) return this.startRedirect({ ...options, presentation: 'redirect' })\n\n const correlationId = randomValue()\n const state = `${correlationId}.${randomValue()}`\n const verifier = randomValue()\n const returnUrl = safeLocalPath(options.returnUrl)\n return new Promise<AuthResult>((resolve, reject) => {\n const timer = setInterval(() => {\n if (!popup.closed) return\n const attempt = this.finishAttempt()\n attempt?.resolve({ status: 'cancelled' })\n }, 250)\n const timeout = setTimeout(() => {\n const attempt = this.finishAttempt()\n popup.close()\n attempt?.reject(new Error('POFSIS Auth popup timed out.'))\n }, timeoutMs)\n this.attempt = {\n presentation: 'popup',\n source: popup,\n state,\n verifier,\n correlationId,\n returnUrl,\n resolve,\n reject,\n timer,\n timeout,\n focus: () => popup.focus(),\n cleanup: () => popup.close(),\n }\n void this.authorizationUrl(options, state, verifier)\n .then((url) => popup.location.replace(url))\n .catch((error) => {\n const attempt = this.finishAttempt()\n popup.close()\n attempt?.reject(error instanceof Error ? error : new Error(String(error)))\n })\n })\n }\n\n private async openModal(options: AuthLaunchOptions): Promise<AuthResult> {\n if (this.attempt) return this.joinAttempt(this.attempt)\n\n const { width, height, timeoutMs, readyTimeoutMs } = this.config.modal\n const previousFocus =\n document.activeElement instanceof HTMLElement ? document.activeElement : null\n const dialog = document.createElement('dialog')\n const header = document.createElement('div')\n const title = document.createElement('span')\n const close = document.createElement('button')\n const iframe = document.createElement('iframe')\n\n dialog.setAttribute('aria-label', 'POFSIS authentication')\n dialog.dataset.pofsisAuthModal = ''\n Object.assign(dialog.style, {\n width: `min(${width}px, calc(100vw - 32px))`,\n height: `min(${height}px, calc(100dvh - 32px))`,\n maxWidth: 'none',\n maxHeight: 'none',\n padding: '0',\n border: '0',\n borderRadius: '12px',\n boxShadow: '0 24px 80px rgba(0, 0, 0, 0.28)',\n overflow: 'hidden',\n })\n Object.assign(header.style, {\n height: '48px',\n padding: '0 10px 0 16px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n background: '#fff',\n borderBottom: '1px solid rgba(0, 0, 0, 0.10)',\n font: '500 14px/20px Inter, sans-serif',\n })\n title.textContent =\n options.screen === 'signup'\n ? 'Create account'\n : options.screen === 'reset'\n ? 'Reset password'\n : 'Sign in'\n close.type = 'button'\n close.setAttribute('aria-label', 'Close authentication')\n close.textContent = '\\u00d7'\n Object.assign(close.style, {\n width: '36px',\n height: '36px',\n padding: '0',\n border: '0',\n borderRadius: '8px',\n background: 'transparent',\n color: '#0a0a0a',\n cursor: 'pointer',\n font: '400 26px/36px sans-serif',\n })\n iframe.title = title.textContent\n iframe.setAttribute(\n 'sandbox',\n 'allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox',\n )\n iframe.setAttribute('allow', 'publickey-credentials-get *; publickey-credentials-create *')\n Object.assign(iframe.style, {\n display: 'block',\n width: '100%',\n height: 'calc(100% - 48px)',\n border: '0',\n background: '#fff',\n })\n header.append(title, close)\n dialog.append(header, iframe)\n document.body.append(dialog)\n\n const styleId = 'pofsis-auth-modal-style'\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style')\n style.id = styleId\n style.textContent =\n '[data-pofsis-auth-modal]::backdrop{background:rgba(10,10,10,.56);backdrop-filter:blur(2px)}'\n document.head.append(style)\n }\n\n const correlationId = randomValue()\n const state = `${correlationId}.${randomValue()}`\n const verifier = randomValue()\n const returnUrl = safeLocalPath(options.returnUrl)\n\n return new Promise<AuthResult>((resolve, reject) => {\n let attempt: AuthAttempt\n const cancel = () => {\n if (this.attempt !== attempt) return\n this.finishAttempt()?.resolve({ status: 'cancelled' })\n }\n close.addEventListener('click', cancel)\n dialog.addEventListener('cancel', (event) => {\n event.preventDefault()\n cancel()\n })\n dialog.addEventListener('click', (event) => {\n if (event.target !== dialog) return\n const rect = dialog.getBoundingClientRect()\n if (\n event.clientX < rect.left ||\n event.clientX > rect.right ||\n event.clientY < rect.top ||\n event.clientY > rect.bottom\n )\n cancel()\n })\n\n const timeout = setTimeout(() => {\n const completed = this.finishAttempt()\n completed?.reject(new Error('POFSIS Auth modal timed out.'))\n }, timeoutMs)\n const source = iframe.contentWindow\n if (!source) {\n dialog.remove()\n clearTimeout(timeout)\n reject(new Error('POFSIS Auth modal could not be created.'))\n return\n }\n attempt = {\n presentation: 'modal',\n source,\n state,\n verifier,\n correlationId,\n returnUrl,\n resolve,\n reject,\n timeout,\n focus: () => close.focus(),\n cleanup: () => {\n dialog.remove()\n previousFocus?.focus()\n },\n }\n this.attempt = attempt\n dialog.showModal()\n close.focus()\n\n void this.authorizationUrl(options, state, verifier)\n .then((url) => {\n if (this.attempt !== attempt) return\n const authOrigin = new URL(url).origin\n attempt.authOrigin = authOrigin\n const initMessage: ModalProtocolMessage = {\n type: MODAL_INIT_MESSAGE_TYPE,\n state,\n correlationId,\n applicationId: this.config.applicationId,\n }\n const sendInit = () =>\n iframe.contentWindow?.postMessage(initMessage, authOrigin)\n iframe.addEventListener('load', sendInit)\n iframe.src = url\n sendInit()\n attempt.timer = setInterval(sendInit, 250)\n attempt.readyTimeout = setTimeout(() => {\n const completed = this.finishAttempt()\n completed?.reject(new Error('POFSIS Auth modal could not be embedded.'))\n }, readyTimeoutMs)\n })\n .catch((error) => {\n const completed = this.finishAttempt()\n completed?.reject(error instanceof Error ? error : new Error(String(error)))\n })\n })\n }\n\n private joinAttempt(attempt: AuthAttempt) {\n attempt.focus()\n return new Promise<AuthResult>((resolve, reject) => {\n const originalResolve = attempt.resolve\n const originalReject = attempt.reject\n attempt.resolve = (value) => {\n originalResolve(value)\n resolve(value)\n }\n attempt.reject = (error) => {\n originalReject(error)\n reject(error)\n }\n })\n }\n\n private finishAttempt() {\n const attempt = this.attempt\n if (!attempt) return null\n if (attempt.timer) clearInterval(attempt.timer)\n clearTimeout(attempt.timeout)\n if (attempt.readyTimeout) clearTimeout(attempt.readyTimeout)\n this.attempt = null\n attempt.cleanup()\n return attempt\n }\n\n private onPopupMessage = (event: MessageEvent<PopupCallbackMessage | ModalProtocolMessage>) => {\n const attempt = this.attempt\n const message = event.data\n if (\n attempt?.presentation === 'modal' &&\n message?.type === MODAL_READY_MESSAGE_TYPE &&\n event.origin === attempt.authOrigin &&\n event.source === attempt.source &&\n message.applicationId === this.config.applicationId &&\n message.correlationId === attempt.correlationId &&\n message.state === attempt.state\n ) {\n attempt.ready = true\n if (attempt.timer) clearInterval(attempt.timer)\n if (attempt.readyTimeout) clearTimeout(attempt.readyTimeout)\n attempt.timer = undefined\n attempt.readyTimeout = undefined\n return\n }\n if (\n !attempt ||\n (attempt.presentation === 'modal' && !attempt.ready) ||\n event.origin !== window.location.origin ||\n event.source !== attempt.source ||\n message?.type !== POPUP_MESSAGE_TYPE ||\n message.correlationId !== attempt.correlationId ||\n correlationFromState(message.state || null) !== attempt.correlationId ||\n message.state !== attempt.state\n )\n return\n\n const completed = this.finishAttempt()\n if (!completed) return\n if (message.error || !message.code) {\n completed.reject(new Error(message.error || 'POFSIS Auth callback was incomplete.'))\n return\n }\n void this.completeCode(message.code, message.state, completed.verifier)\n .then(() => {\n if (completed.returnUrl) window.history.replaceState(null, '', completed.returnUrl)\n completed.resolve({ status: 'authenticated', user: this.getUser()! })\n })\n .catch((error) => {\n completed.reject(error instanceof Error ? error : new Error(String(error)))\n })\n }\n\n private async completeCode(code: string, state: string, verifier: string) {\n if (!state || !verifier) throw new Error('Authentication state could not be verified.')\n const client = await this.loadClient()\n this.accept(await exchangeCode(this.config, code, verifier, client))\n }\n\n async completeRedirectCallback(code: string, state: string) {\n const expected = sessionStorage.getItem(this.storageKey('state'))\n const verifier = sessionStorage.getItem(this.storageKey('verifier'))\n sessionStorage.removeItem(this.storageKey('state'))\n sessionStorage.removeItem(this.storageKey('verifier'))\n if (!expected || !verifier || state !== expected) {\n throw new Error('Authentication state could not be verified.')\n }\n await this.completeCode(code, state, verifier)\n }\n}\n\nexport function createPofsisAuth(config: PofsisAuthClientConfig) {\n return new PofsisAuthClient(config)\n}\n"],"mappings":"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"}
|