@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.
Files changed (44) hide show
  1. package/Documentation.md +151 -147
  2. package/README.md +143 -133
  3. package/dist/PofsisAuth.d.ts +1 -1
  4. package/dist/PofsisAuth.d.ts.map +1 -1
  5. package/dist/{PofsisAuthClient-CEw_lL5S.js → PofsisAuthClient-Duybofpq.js} +162 -46
  6. package/dist/PofsisAuthClient-Duybofpq.js.map +1 -0
  7. package/dist/PofsisAuthClient-c4lzLzjV.cjs +2 -0
  8. package/dist/PofsisAuthClient-c4lzLzjV.cjs.map +1 -0
  9. package/dist/{RequireAuth-CPhXupYh.cjs → RequireAuth-BkYhk-9p.cjs} +2 -2
  10. package/dist/{RequireAuth-CPhXupYh.cjs.map → RequireAuth-BkYhk-9p.cjs.map} +1 -1
  11. package/dist/{RequireAuth-DFa8_MR1.js → RequireAuth-DroX56rd.js} +67 -62
  12. package/dist/{RequireAuth-DFa8_MR1.js.map → RequireAuth-DroX56rd.js.map} +1 -1
  13. package/dist/auth/authLaunch.d.ts.map +1 -1
  14. package/dist/auth/config.d.ts.map +1 -1
  15. package/dist/core/PofsisAuthClient.d.ts +2 -0
  16. package/dist/core/PofsisAuthClient.d.ts.map +1 -1
  17. package/dist/core/index.d.ts +2 -2
  18. package/dist/core/index.d.ts.map +1 -1
  19. package/dist/core/popupProtocol.d.ts +11 -1
  20. package/dist/core/popupProtocol.d.ts.map +1 -1
  21. package/dist/core.cjs +1 -1
  22. package/dist/core.js +2 -2
  23. package/dist/elements/index.d.ts.map +1 -1
  24. package/dist/elements.cjs +1 -1
  25. package/dist/elements.cjs.map +1 -1
  26. package/dist/elements.js +8 -3
  27. package/dist/elements.js.map +1 -1
  28. package/dist/index.cjs +1 -1
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -3
  32. package/dist/pofsis-auth-elements.js +1 -1
  33. package/dist/pofsis-auth-elements.js.map +1 -1
  34. package/dist/react/index.d.ts +1 -1
  35. package/dist/react/index.d.ts.map +1 -1
  36. package/dist/react.cjs +1 -1
  37. package/dist/react.js +1 -1
  38. package/dist/types.d.ts +13 -2
  39. package/dist/types.d.ts.map +1 -1
  40. package/docs/popup-integration.md +188 -162
  41. package/package.json +87 -87
  42. package/dist/PofsisAuthClient-B3YHqgZL.cjs +0 -2
  43. package/dist/PofsisAuthClient-B3YHqgZL.cjs.map +0 -1
  44. 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
- if (t || s.push("applicationId"), n || s.push("apiBaseUrl"), r || s.push("authUrl"), s.length) throw Error(`@pofsis-nbt/pofsis-auth missing config: ${s.join(", ")}`);
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 C(e) {
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 w(e = window.location.origin) {
168
- if (!window.opener || window.opener.closed) return !1;
169
- let t = new URLSearchParams(window.location.search), n = t.get("state") || void 0, r = {
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: C(n || null)
184
+ correlationId: r
175
185
  };
176
- return window.opener.postMessage(r, e), window.close(), !0;
186
+ return o.postMessage(s, e), i && window.close(), !0;
177
187
  }
178
- //#endregion
179
- //#region src/auth/pkce.ts
180
- var T = (e) => btoa(String.fromCharCode(...e)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""), E = () => T(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32)));
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 O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) => ({
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
- }), A = class {
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 && (e.popup.close(), e.resolve({ status: "cancelled" })), this.subscribers.clear();
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 = k(e), this.emit();
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 (e.presentation ?? "popup") === "popup" ? this.openPopup({
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 D(n),
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 = E(), n = E();
317
+ let t = O(), n = O();
307
318
  sessionStorage.setItem(this.storageKey("state"), t), sessionStorage.setItem(this.storageKey("verifier"), n);
308
- let r = O(e.returnUrl);
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 && !this.attempt.popup.closed) return this.attempt.popup.focus(), new Promise((e, t) => {
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 = E(), l = `${c}.${E()}`, u = E(), d = O(e.returnUrl);
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
- popup: s,
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 (!t || e.origin !== window.location.origin || e.source !== t.popup || n?.type !== "pofsis-auth:callback" || n.correlationId !== t.correlationId || C(n.state || null) !== t.correlationId || n.state !== t.state) return;
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.popup.close(), r.reject(Error(n.error || "POFSIS Auth callback was incomplete."));
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.popup.close(), r.returnUrl && window.history.replaceState(null, "", r.returnUrl), r.resolve({
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.popup.close(), r.reject(e instanceof Error ? e : Error(String(e)));
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 j(e) {
384
- return new A(e);
499
+ function N(e) {
500
+ return new M(e);
385
501
  }
386
502
  //#endregion
387
- export { f as a, c, b as i, l, j as n, u as o, w as r, s, A as t };
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-CEw_lL5S.js.map
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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"}