@xinosolutions/auth-sdk 0.1.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20,14 +20,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ LoginBridgeTimeoutError: () => LoginBridgeTimeoutError,
23
24
  LoginTimeoutError: () => LoginTimeoutError,
24
25
  PopupBlockedError: () => PopupBlockedError,
25
26
  PopupClosedError: () => PopupClosedError,
27
+ SessionBridgeError: () => SessionBridgeError,
26
28
  XSAuthDeniedError: () => XSAuthDeniedError,
27
29
  createPkcePair: () => createPkcePair,
28
- loginWithXS: () => loginWithXS
30
+ idTokenIncludesMfa: () => idTokenIncludesMfa,
31
+ isLoginRequiredError: () => isLoginRequiredError,
32
+ isPrimaryAccountError: () => isPrimaryAccountError,
33
+ loginWithXS: () => loginWithXS,
34
+ openSessionBridge: () => openSessionBridge2,
35
+ parseIdTokenAmr: () => parseIdTokenAmr,
36
+ signOutWithXS: () => signOutWithXS2
29
37
  });
30
38
  module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/errors.ts
31
41
  var PopupBlockedError = class extends Error {
32
42
  name = "PopupBlockedError";
33
43
  };
@@ -47,7 +57,327 @@ var XSAuthDeniedError = class extends Error {
47
57
  this.description = description;
48
58
  }
49
59
  };
60
+ var LoginBridgeTimeoutError = class extends Error {
61
+ name = "LoginBridgeTimeoutError";
62
+ };
63
+
64
+ // src/session-bridge.ts
65
+ var SessionBridgeError = class extends Error {
66
+ name = "SessionBridgeError";
67
+ errorCode;
68
+ constructor(errorCode, message) {
69
+ super(message || errorCode);
70
+ this.errorCode = errorCode;
71
+ }
72
+ };
73
+ var BRIDGE_STATE_KEY = "__xs_bridge_state";
74
+ function parseAccounts(raw) {
75
+ if (!Array.isArray(raw)) return [];
76
+ return raw.map((item) => {
77
+ if (!item || typeof item !== "object") return null;
78
+ const row = item;
79
+ const sessionId = typeof row.sessionId === "string" ? row.sessionId : typeof row.session_id === "string" ? row.session_id : "";
80
+ const userId = typeof row.userId === "string" ? row.userId : typeof row.user_id === "string" ? row.user_id : "";
81
+ const email = typeof row.email === "string" ? row.email : "";
82
+ const name = typeof row.name === "string" ? row.name : email;
83
+ if (!sessionId || !email) return null;
84
+ return {
85
+ sessionId,
86
+ userId,
87
+ email,
88
+ name,
89
+ isPrimary: row.isPrimary === true || row.is_primary === true
90
+ };
91
+ }).filter((x) => x !== null);
92
+ }
93
+ function hiddenBridgePopupFeatures() {
94
+ return "width=1,height=1,left=-10000,top=-10000,resizable=no,scrollbars=no";
95
+ }
96
+ function randomBridgeState() {
97
+ const bytes = new Uint8Array(32);
98
+ crypto.getRandomValues(bytes);
99
+ let binary = "";
100
+ for (let i = 0; i < bytes.length; i++) {
101
+ binary += String.fromCharCode(bytes[i]);
102
+ }
103
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
104
+ }
105
+ async function openSessionBridge(opts, authBaseUrl) {
106
+ const parentOrigin = opts.parentOrigin ?? globalThis.location?.origin;
107
+ if (!parentOrigin || typeof window === "undefined") {
108
+ throw new Error(
109
+ "openSessionBridge requires a browser Window and explicit parentOrigin (or window.location)."
110
+ );
111
+ }
112
+ const normalizedBase = new URL(authBaseUrl);
113
+ const authOrigin = normalizedBase.origin;
114
+ const state = randomBridgeState();
115
+ sessionStorage.setItem(BRIDGE_STATE_KEY, state);
116
+ const params = new URLSearchParams({
117
+ client_id: opts.clientId,
118
+ parent_origin: parentOrigin,
119
+ state
120
+ });
121
+ const bridgeUrl = `${normalizedBase.href.replace(/\/?$/u, "")}/session/bridge?${params.toString()}`;
122
+ const popup = window.open(
123
+ bridgeUrl,
124
+ `xs-auth-bridge-${crypto.randomUUID()}`,
125
+ hiddenBridgePopupFeatures()
126
+ );
127
+ if (!popup) throw new PopupBlockedError();
128
+ const timeoutMs = opts.timeoutMs !== void 0 ? opts.timeoutMs : 12e4;
129
+ let cleaned = false;
130
+ let closePoll;
131
+ const teardown = () => {
132
+ if (cleaned) return;
133
+ cleaned = true;
134
+ window.removeEventListener("message", handleMessage);
135
+ if (closePoll !== void 0) clearInterval(closePoll);
136
+ sessionStorage.removeItem(BRIDGE_STATE_KEY);
137
+ try {
138
+ popup.close();
139
+ } catch {
140
+ }
141
+ };
142
+ const pending = /* @__PURE__ */ new Map();
143
+ let bridgeReady = false;
144
+ let readyResolve = null;
145
+ let readyReject = null;
146
+ const readyPromise = new Promise((resolve, reject) => {
147
+ readyResolve = resolve;
148
+ readyReject = reject;
149
+ });
150
+ const handleMessage = (event) => {
151
+ if (event.origin !== authOrigin) return;
152
+ const d = event.data;
153
+ if (d?.source !== "xs-auth") return;
154
+ const st = typeof d.state === "string" ? d.state : "";
155
+ if (!st || st !== sessionStorage.getItem(BRIDGE_STATE_KEY)) return;
156
+ if (d.type === "bridge_ready") {
157
+ bridgeReady = true;
158
+ readyResolve?.();
159
+ return;
160
+ }
161
+ const requestId = typeof d.requestId === "string" ? d.requestId : "";
162
+ if (!requestId) return;
163
+ const entry = pending.get(requestId);
164
+ if (!entry) return;
165
+ pending.delete(requestId);
166
+ if (typeof d.error === "string" && d.error.length > 0) {
167
+ entry.reject(
168
+ new SessionBridgeError(
169
+ String(d.error),
170
+ typeof d.error_description === "string" ? d.error_description : ""
171
+ )
172
+ );
173
+ return;
174
+ }
175
+ if (d.type === "result") {
176
+ entry.resolve(d);
177
+ }
178
+ };
179
+ window.addEventListener("message", handleMessage);
180
+ closePoll = window.setInterval(() => {
181
+ if (!popup.closed) return;
182
+ if (cleaned) return;
183
+ for (const [, entry] of pending) {
184
+ entry.reject(new PopupClosedError());
185
+ }
186
+ pending.clear();
187
+ readyReject?.(new PopupClosedError());
188
+ teardown();
189
+ }, 280);
190
+ const readyTimer = window.setTimeout(() => {
191
+ if (bridgeReady) return;
192
+ readyReject?.(new LoginBridgeTimeoutError());
193
+ teardown();
194
+ }, timeoutMs);
195
+ try {
196
+ await readyPromise;
197
+ } catch (error) {
198
+ clearTimeout(readyTimer);
199
+ throw error;
200
+ }
201
+ clearTimeout(readyTimer);
202
+ const sendRequest = (type, extra = {}) => {
203
+ if (popup.closed) {
204
+ return Promise.reject(new PopupClosedError());
205
+ }
206
+ const requestId = crypto.randomUUID();
207
+ return new Promise((resolve, reject) => {
208
+ const timer = window.setTimeout(() => {
209
+ pending.delete(requestId);
210
+ reject(new LoginBridgeTimeoutError());
211
+ }, timeoutMs);
212
+ pending.set(requestId, {
213
+ resolve: (value) => {
214
+ clearTimeout(timer);
215
+ resolve(value);
216
+ },
217
+ reject: (error) => {
218
+ clearTimeout(timer);
219
+ reject(error);
220
+ }
221
+ });
222
+ try {
223
+ popup.postMessage(
224
+ {
225
+ source: "xs-auth-opener",
226
+ state,
227
+ client_id: opts.clientId,
228
+ requestId,
229
+ type,
230
+ ...extra
231
+ },
232
+ authOrigin
233
+ );
234
+ } catch {
235
+ pending.delete(requestId);
236
+ clearTimeout(timer);
237
+ reject(new SessionBridgeError("post_message_failed", "Could not reach the session bridge."));
238
+ }
239
+ });
240
+ };
241
+ return {
242
+ async listAccounts() {
243
+ const result = await sendRequest("list_accounts");
244
+ return parseAccounts(result.accounts);
245
+ },
246
+ async revokeAccount(sessionId) {
247
+ const result = await sendRequest("revoke", { session_id: sessionId.trim() });
248
+ const accounts = parseAccounts(result.accounts);
249
+ const remainingCount = typeof result.remainingCount === "number" ? result.remainingCount : accounts.length;
250
+ return { accounts, remainingCount };
251
+ },
252
+ async revokeAll() {
253
+ await sendRequest("revoke_all");
254
+ },
255
+ async setPrimary(sessionId) {
256
+ const result = await sendRequest("set_primary", { session_id: sessionId.trim() });
257
+ return parseAccounts(result.accounts);
258
+ },
259
+ close() {
260
+ teardown();
261
+ }
262
+ };
263
+ }
264
+ function isPrimaryAccountError(error) {
265
+ return error instanceof SessionBridgeError && error.errorCode === "primary_account";
266
+ }
267
+
268
+ // src/sign-out.ts
269
+ var SIGN_OUT_STATE_KEY = "__xs_sign_out_state";
270
+ function popupWindowFeatures(width, height) {
271
+ const win = window;
272
+ const outerW = win.outerWidth > 0 ? win.outerWidth : win.innerWidth;
273
+ const outerH = win.outerHeight > 0 ? win.outerHeight : win.innerHeight;
274
+ const screenX = win.screenX ?? win.screenLeft ?? 0;
275
+ const screenY = win.screenY ?? win.screenTop ?? 0;
276
+ const left = Math.round(screenX + Math.max(0, (outerW - width) / 2));
277
+ const top = Math.round(screenY + Math.max(0, (outerH - height) / 2));
278
+ return `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
279
+ }
280
+ function randomState() {
281
+ const bytes = new Uint8Array(32);
282
+ crypto.getRandomValues(bytes);
283
+ let binary = "";
284
+ for (let i = 0; i < bytes.length; i++) {
285
+ binary += String.fromCharCode(bytes[i]);
286
+ }
287
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
288
+ }
289
+ function parseSignOutResult(raw, data) {
290
+ return {
291
+ action: raw,
292
+ revokedCurrent: data.revokedCurrent === true,
293
+ remainingCount: typeof data.remainingCount === "number" && Number.isFinite(data.remainingCount) ? Math.max(0, data.remainingCount) : 0
294
+ };
295
+ }
296
+ async function signOutWithXS(opts, authBaseUrl) {
297
+ const parentOrigin = opts.parentOrigin ?? globalThis.location?.origin;
298
+ if (!parentOrigin || typeof window === "undefined") {
299
+ throw new Error(
300
+ "signOutWithXS requires a browser Window and explicit parentOrigin (or window.location)."
301
+ );
302
+ }
303
+ const normalizedBase = new URL(authBaseUrl);
304
+ const authOrigin = normalizedBase.origin;
305
+ const state = randomState();
306
+ sessionStorage.setItem(SIGN_OUT_STATE_KEY, state);
307
+ const params = new URLSearchParams({
308
+ client_id: opts.clientId,
309
+ parent_origin: parentOrigin,
310
+ state
311
+ });
312
+ if (opts.activeUserId?.trim()) {
313
+ params.set("active_user_id", opts.activeUserId.trim());
314
+ }
315
+ const url = `${normalizedBase.href.replace(/\/?$/u, "")}/session/sign-out?${params.toString()}`;
316
+ const popup = window.open(
317
+ url,
318
+ `xs-auth-signout-${crypto.randomUUID()}`,
319
+ popupWindowFeatures(480, 640)
320
+ );
321
+ if (!popup) throw new PopupBlockedError();
322
+ const timeoutMs = opts.timeoutMs !== void 0 ? opts.timeoutMs : 12e4;
323
+ return await new Promise((resolve, reject) => {
324
+ let cleaned = false;
325
+ const teardown = () => {
326
+ if (cleaned) return;
327
+ cleaned = true;
328
+ window.removeEventListener("message", handleMessage);
329
+ clearInterval(closePoll);
330
+ clearTimeout(timer);
331
+ sessionStorage.removeItem(SIGN_OUT_STATE_KEY);
332
+ try {
333
+ popup.close();
334
+ } catch {
335
+ }
336
+ };
337
+ const fail = (error) => {
338
+ teardown();
339
+ reject(error);
340
+ };
341
+ const timer = window.setTimeout(() => {
342
+ fail(new LoginBridgeTimeoutError());
343
+ }, timeoutMs);
344
+ const handleMessage = (event) => {
345
+ if (event.origin !== authOrigin) return;
346
+ const d = event.data;
347
+ if (d?.source !== "xs-auth") return;
348
+ const st = typeof d.state === "string" ? d.state : "";
349
+ if (!st || st !== sessionStorage.getItem(SIGN_OUT_STATE_KEY)) return;
350
+ if (d.type === "sign_out_cancelled") {
351
+ teardown();
352
+ resolve(parseSignOutResult("cancelled", d));
353
+ return;
354
+ }
355
+ if (d.type === "sign_out_complete") {
356
+ teardown();
357
+ const actionRaw = typeof d.action === "string" ? d.action : "revoked_one";
358
+ const action = actionRaw === "revoked_all" ? "revoked_all" : actionRaw === "cancelled" ? "cancelled" : "revoked_one";
359
+ resolve(parseSignOutResult(action, d));
360
+ }
361
+ };
362
+ window.addEventListener("message", handleMessage);
363
+ const closePoll = window.setInterval(() => {
364
+ if (!popup.closed) return;
365
+ if (cleaned) return;
366
+ if (!sessionStorage.getItem(SIGN_OUT_STATE_KEY)) return;
367
+ fail(new PopupClosedError());
368
+ }, 280);
369
+ });
370
+ }
371
+
372
+ // src/index.ts
50
373
  var XS_AUTH_BASE_URL = "https://auth.xinosolutions.com";
374
+ function openSessionBridge2(opts) {
375
+ return openSessionBridge(opts, XS_AUTH_BASE_URL);
376
+ }
377
+ function signOutWithXS2(opts) {
378
+ const authBase = opts.authBaseUrl?.trim() || XS_AUTH_BASE_URL;
379
+ return signOutWithXS(opts, authBase);
380
+ }
51
381
  function bytesBuffer(len) {
52
382
  const out = new Uint8Array(len);
53
383
  crypto.getRandomValues(out);
@@ -86,8 +416,26 @@ function parseSdkUser(raw) {
86
416
  if (lastName) user.lastName = lastName;
87
417
  return user;
88
418
  }
419
+ function resolvePrompt(opts) {
420
+ if (opts.prompt) return opts.prompt;
421
+ if (opts.preferPrimary) return "none";
422
+ return void 0;
423
+ }
424
+ function authPublicPathFromBase(authBaseUrl) {
425
+ try {
426
+ const pathname = new URL(authBaseUrl).pathname.replace(/\/$/u, "");
427
+ return pathname === "/" ? "" : pathname;
428
+ } catch {
429
+ return "";
430
+ }
431
+ }
432
+ function maybeSetPublicPath(params, authBaseUrl) {
433
+ const publicPath = authPublicPathFromBase(authBaseUrl);
434
+ if (publicPath) params.set("public_path", publicPath);
435
+ }
89
436
  async function loginWithXS(opts) {
90
- const normalizedBase = normalizeBaseUrl(XS_AUTH_BASE_URL);
437
+ const authBase = opts.authBaseUrl?.trim() || XS_AUTH_BASE_URL;
438
+ const normalizedBase = normalizeBaseUrl(authBase);
91
439
  const authOrigin = normalizedBase.origin;
92
440
  const parentOrigin = opts.parentOrigin ?? globalThis.location?.origin;
93
441
  if (!parentOrigin || typeof window === "undefined") {
@@ -95,7 +443,7 @@ async function loginWithXS(opts) {
95
443
  "loginWithXS requires a browser Window and explicit parentOrigin (or window.location)."
96
444
  );
97
445
  }
98
- const timeoutMs = opts.timeoutMs !== void 0 ? opts.timeoutMs : 12e4;
446
+ const timeoutMs = opts.timeoutMs !== void 0 ? opts.timeoutMs : 18e4;
99
447
  const state = randomBase64State();
100
448
  sessionStorage.setItem(STATE_KEY_STORAGE, state);
101
449
  const nonce = opts.useNonce ? randomBase64State() : void 0;
@@ -110,13 +458,17 @@ async function loginWithXS(opts) {
110
458
  });
111
459
  if (opts.scope?.trim()) params.set("scope", opts.scope.trim());
112
460
  if (nonce) params.set("nonce", nonce);
461
+ const prompt = resolvePrompt(opts);
462
+ if (prompt) params.set("prompt", prompt);
463
+ if (opts.accountId?.trim()) params.set("account_id", opts.accountId.trim());
464
+ maybeSetPublicPath(params, authBase);
113
465
  const authorizeUrl = `${normalizedBase.href.replace(/\/?$/u, "")}/authorize?${params.toString()}`;
114
- const popupWidth = 480;
115
- const popupHeight = 640;
466
+ const popupWidth = prompt === "none" ? 420 : 480;
467
+ const popupHeight = prompt === "none" ? 120 : 640;
116
468
  const popup = window.open(
117
469
  authorizeUrl,
118
470
  `xs-auth-${crypto.randomUUID()}`,
119
- popupWindowFeatures(popupWidth, popupHeight)
471
+ popupWindowFeatures2(popupWidth, popupHeight)
120
472
  );
121
473
  if (!popup) throw new PopupBlockedError();
122
474
  return await new Promise((resolve, reject) => {
@@ -179,7 +531,7 @@ async function loginWithXS(opts) {
179
531
  window.removeEventListener("message", handleMessage);
180
532
  clearInterval(closePoll);
181
533
  cleaned = true;
182
- resolve({ user, idToken });
534
+ resolve({ user, idToken, mfaVerified: idTokenIncludesMfa(idToken) });
183
535
  try {
184
536
  popup.close();
185
537
  } catch {
@@ -195,13 +547,38 @@ async function loginWithXS(opts) {
195
547
  }, 280);
196
548
  });
197
549
  }
550
+ function idTokenIncludesMfa(idToken) {
551
+ const amr = parseIdTokenAmr(idToken);
552
+ return Array.isArray(amr) && amr.includes("mfa");
553
+ }
554
+ function parseIdTokenAmr(idToken) {
555
+ const payload = parseJwtPayload(idToken);
556
+ if (!payload || !("amr" in payload)) return null;
557
+ const amr = payload.amr;
558
+ if (Array.isArray(amr)) {
559
+ return amr.filter((v) => typeof v === "string");
560
+ }
561
+ if (typeof amr === "string" && amr.trim()) return [amr.trim()];
562
+ return null;
563
+ }
564
+ function parseJwtPayload(token) {
565
+ const parts = token.split(".");
566
+ if (parts.length < 2) return null;
567
+ try {
568
+ const json = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
569
+ const parsed = JSON.parse(json);
570
+ return parsed && typeof parsed === "object" ? parsed : null;
571
+ } catch {
572
+ return null;
573
+ }
574
+ }
198
575
  function randomBase64State() {
199
576
  return base64UrlEncode(bytesBuffer(32));
200
577
  }
201
578
  function normalizeBaseUrl(s) {
202
579
  return new URL(s);
203
580
  }
204
- function popupWindowFeatures(width, height) {
581
+ function popupWindowFeatures2(width, height) {
205
582
  const win = window;
206
583
  const outerW = win.outerWidth > 0 ? win.outerWidth : win.innerWidth;
207
584
  const outerH = win.outerHeight > 0 ? win.outerHeight : win.innerHeight;
@@ -211,13 +588,24 @@ function popupWindowFeatures(width, height) {
211
588
  const top = Math.round(screenY + Math.max(0, (outerH - height) / 2));
212
589
  return `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
213
590
  }
591
+ function isLoginRequiredError(error) {
592
+ return error instanceof XSAuthDeniedError && error.errorCode === "login_required";
593
+ }
214
594
  // Annotate the CommonJS export names for ESM import in node:
215
595
  0 && (module.exports = {
596
+ LoginBridgeTimeoutError,
216
597
  LoginTimeoutError,
217
598
  PopupBlockedError,
218
599
  PopupClosedError,
600
+ SessionBridgeError,
219
601
  XSAuthDeniedError,
220
602
  createPkcePair,
221
- loginWithXS
603
+ idTokenIncludesMfa,
604
+ isLoginRequiredError,
605
+ isPrimaryAccountError,
606
+ loginWithXS,
607
+ openSessionBridge,
608
+ parseIdTokenAmr,
609
+ signOutWithXS
222
610
  });
223
611
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/** Popup was blocked by the browser or environment. */\r\nexport class PopupBlockedError extends Error {\r\n readonly name = 'PopupBlockedError';\r\n}\r\n\r\n/** User closed the popup before completing login. */\r\nexport class PopupClosedError extends Error {\r\n readonly name = 'PopupClosedError';\r\n}\r\n\r\n/** XS Auth popup did not complete within timeout. */\r\nexport class LoginTimeoutError extends Error {\r\n readonly name = 'LoginTimeoutError';\r\n}\r\n\r\n/** XS Auth returned an OAuth-style error inside postMessage. */\r\nexport class XSAuthDeniedError extends Error {\r\n readonly name = 'XSAuthDeniedError';\r\n readonly errorCode: string;\r\n readonly description: string;\r\n\r\n constructor(errorCode: string, description: string) {\r\n super(description || errorCode || 'xs_auth_denied');\r\n this.errorCode = errorCode;\r\n this.description = description;\r\n }\r\n}\r\n\r\n/** XS Auth server — baked in at build time (local vs production). */\r\nconst XS_AUTH_BASE_URL = __XS_AUTH_BASE_URL__;\r\n\r\n/** Signed-in user profile from XS Auth. */\r\nexport interface XSAuthUser {\r\n email: string;\r\n firstName?: string;\r\n lastName?: string;\r\n}\r\n\r\nexport interface LoginWithXSOptions {\r\n /** Your app's public client id from Xino Solutions. */\r\n clientId: string;\r\n /** Must be on your XS Auth client's allowed domains list (normally `window.location.origin`). */\r\n parentOrigin?: string;\r\n timeoutMs?: number;\r\n scope?: string;\r\n /**\r\n * Request a `nonce` inside `idToken` — your backend should verify it matches when validating the JWT.\r\n */\r\n useNonce?: boolean;\r\n}\r\n\r\nexport interface LoginWithXSResult {\r\n user: XSAuthUser;\r\n /** Short-lived signed JWT — send to your backend to create a session. */\r\n idToken: string;\r\n}\r\n\r\nfunction bytesBuffer(len: number): Uint8Array {\r\n const out = new Uint8Array(len);\r\n crypto.getRandomValues(out);\r\n return out;\r\n}\r\n\r\nfunction base64UrlEncode(buf: Uint8Array | ArrayBuffer): string {\r\n const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);\r\n let binary = '';\r\n const chunkSize = 0x8000;\r\n for (let i = 0; i < bytes.length; i += chunkSize) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\r\n }\r\n const b64 = btoa(binary);\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/u, '');\r\n}\r\n\r\nasync function pkceVerifierAndChallenge(): Promise<{\r\n verifier: string;\r\n challenge: string;\r\n}> {\r\n const verifier = base64UrlEncode(bytesBuffer(64));\r\n const data = new TextEncoder().encode(verifier);\r\n const digest = await crypto.subtle.digest('SHA-256', data);\r\n const challenge = base64UrlEncode(digest);\r\n return { verifier, challenge };\r\n}\r\n\r\n/** PKCE helpers for tests / custom callers. */\r\nexport async function createPkcePair(): Promise<{\r\n verifier: string;\r\n challenge: string;\r\n}> {\r\n return pkceVerifierAndChallenge();\r\n}\r\n\r\nconst STATE_KEY_STORAGE = '__xs_login_state';\r\n\r\nfunction parseSdkUser(raw: unknown): XSAuthUser | null {\r\n if (!raw || typeof raw !== 'object') return null;\r\n const u = raw as Record<string, unknown>;\r\n const email = typeof u.email === 'string' ? u.email.trim() : '';\r\n if (!email) return null;\r\n const user: XSAuthUser = { email };\r\n const firstName =\r\n typeof u.firstName === 'string' ? u.firstName.trim() : '';\r\n const lastName = typeof u.lastName === 'string' ? u.lastName.trim() : '';\r\n if (firstName) user.firstName = firstName;\r\n if (lastName) user.lastName = lastName;\r\n return user;\r\n}\r\n\r\n/**\r\n * Opens the XS Auth sign-in popup and returns the signed-in user plus a verifiable `idToken`.\r\n *\r\n * All Auth-Server HTTP calls happen inside the popup (same origin). The host app only\r\n * opens the popup and exchanges postMessages with the PKCE verifier — no fetch to Auth-Server.\r\n */\r\nexport async function loginWithXS(\r\n opts: LoginWithXSOptions,\r\n): Promise<LoginWithXSResult> {\r\n const normalizedBase = normalizeBaseUrl(XS_AUTH_BASE_URL);\r\n const authOrigin = normalizedBase.origin;\r\n const parentOrigin = (opts.parentOrigin ?? globalThis.location?.origin) as\r\n | string\r\n | undefined;\r\n if (!parentOrigin || typeof window === 'undefined') {\r\n throw new Error(\r\n 'loginWithXS requires a browser Window and explicit parentOrigin (or window.location).',\r\n );\r\n }\r\n\r\n const timeoutMs =\r\n opts.timeoutMs !== undefined ? opts.timeoutMs : 120_000;\r\n\r\n const state = randomBase64State();\r\n sessionStorage.setItem(STATE_KEY_STORAGE, state);\r\n\r\n const nonce = opts.useNonce ? randomBase64State() : undefined;\r\n const pair = await pkceVerifierAndChallenge();\r\n\r\n const params = new URLSearchParams({\r\n client_id: opts.clientId,\r\n state,\r\n code_challenge: pair.challenge,\r\n code_challenge_method: 'S256',\r\n parent_origin: parentOrigin,\r\n response_mode: 'popup',\r\n });\r\n if (opts.scope?.trim()) params.set('scope', opts.scope.trim());\r\n if (nonce) params.set('nonce', nonce);\r\n\r\n const authorizeUrl = `${normalizedBase.href.replace(/\\/?$/u, '')}/authorize?${params.toString()}`;\r\n\r\n const popupWidth = 480;\r\n const popupHeight = 640;\r\n const popup = window.open(\r\n authorizeUrl,\r\n `xs-auth-${crypto.randomUUID()}`,\r\n popupWindowFeatures(popupWidth, popupHeight),\r\n );\r\n if (!popup) throw new PopupBlockedError();\r\n\r\n return await new Promise<LoginWithXSResult>((resolve, reject) => {\r\n let cleaned = false;\r\n const teardown = (): void => {\r\n if (cleaned) return;\r\n cleaned = true;\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n clearInterval(closePoll);\r\n clearTimeout(timer);\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n const fail = (e: unknown): void => {\r\n teardown();\r\n reject(e instanceof Error ? e : new Error(String(e)));\r\n };\r\n\r\n const timer = window.setTimeout(() => {\r\n fail(new LoginTimeoutError());\r\n }, timeoutMs);\r\n\r\n const handleMessage = (event: MessageEvent): void => {\r\n if (event.origin !== authOrigin) return;\r\n const d = event.data as Partial<Record<string, unknown>>;\r\n if (d?.source !== 'xs-auth') return;\r\n\r\n const st = typeof d.state === 'string' ? d.state : '';\r\n if (!st || st !== sessionStorage.getItem(STATE_KEY_STORAGE)) return;\r\n\r\n if (typeof d.error === 'string' && d.error.length > 0) {\r\n teardown();\r\n reject(\r\n new XSAuthDeniedError(\r\n String(d.error),\r\n typeof d.error_description === 'string'\r\n ? d.error_description\r\n : '',\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n if (d.type === 'need_verifier') {\r\n try {\r\n popup.postMessage(\r\n {\r\n source: 'xs-auth-opener',\r\n state: st,\r\n code_verifier: pair.verifier,\r\n client_id: opts.clientId,\r\n },\r\n authOrigin,\r\n );\r\n } catch {\r\n fail(new XSAuthDeniedError('exchange_failed', 'Sign in could not be completed.'));\r\n }\r\n return;\r\n }\r\n\r\n const idToken =\r\n typeof d.id_token === 'string'\r\n ? d.id_token\r\n : typeof d.idToken === 'string'\r\n ? d.idToken\r\n : '';\r\n const user = parseSdkUser(d.user);\r\n if (!idToken || !user) return;\r\n\r\n sessionStorage.removeItem(STATE_KEY_STORAGE);\r\n clearTimeout(timer);\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n clearInterval(closePoll);\r\n cleaned = true;\r\n\r\n resolve({ user, idToken });\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage as EventListener);\r\n\r\n const closePoll = window.setInterval(() => {\r\n if (!popup.closed) return;\r\n if (cleaned) return;\r\n const pending = sessionStorage.getItem(STATE_KEY_STORAGE);\r\n if (!pending) return;\r\n fail(new PopupClosedError());\r\n }, 280);\r\n });\r\n}\r\n\r\nfunction randomBase64State(): string {\r\n return base64UrlEncode(bytesBuffer(32));\r\n}\r\n\r\nfunction normalizeBaseUrl(s: string): URL {\r\n return new URL(s);\r\n}\r\n\r\n/** Center popup over the opener window (falls back to screen center). */\r\nfunction popupWindowFeatures(width: number, height: number): string {\r\n const win = window;\r\n const outerW = win.outerWidth > 0 ? win.outerWidth : win.innerWidth;\r\n const outerH = win.outerHeight > 0 ? win.outerHeight : win.innerHeight;\r\n const screenX = win.screenX ?? win.screenLeft ?? 0;\r\n const screenY = win.screenY ?? win.screenTop ?? 0;\r\n const left = Math.round(screenX + Math.max(0, (outerW - width) / 2));\r\n const top = Math.round(screenY + Math.max(0, (outerH - height) / 2));\r\n return `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/session-bridge.ts","../src/sign-out.ts"],"sourcesContent":["import {\r\n LoginTimeoutError,\r\n PopupBlockedError,\r\n PopupClosedError,\r\n XSAuthDeniedError,\r\n} from './errors';\r\nimport {\r\n isPrimaryAccountError,\r\n openSessionBridge as openSessionBridgeInternal,\r\n SessionBridgeError,\r\n type OpenSessionBridgeOptions,\r\n type SessionBridge,\r\n type XSBrowserAccount,\r\n} from './session-bridge';\r\n\r\nimport {\r\n signOutWithXS as signOutWithXSInternal,\r\n type SignOutAction,\r\n type SignOutWithXSOptions,\r\n type SignOutWithXSResult,\r\n} from './sign-out';\r\n\r\nexport {\r\n LoginBridgeTimeoutError,\r\n LoginTimeoutError,\r\n PopupBlockedError,\r\n PopupClosedError,\r\n XSAuthDeniedError,\r\n} from './errors';\r\n\r\nexport {\r\n isPrimaryAccountError,\r\n SessionBridgeError,\r\n type OpenSessionBridgeOptions,\r\n type SessionBridge,\r\n type XSBrowserAccount,\r\n};\r\n\r\nexport {\r\n type SignOutAction,\r\n type SignOutWithXSOptions,\r\n type SignOutWithXSResult,\r\n};\r\n\r\n/** XS Auth server — baked in at build time (local vs production). */\r\nconst XS_AUTH_BASE_URL = __XS_AUTH_BASE_URL__;\r\n\r\n/** Opens the Auth-Server session bridge popup (multi-account sign-out). */\r\nexport function openSessionBridge(\r\n opts: OpenSessionBridgeOptions,\r\n): Promise<SessionBridge> {\r\n return openSessionBridgeInternal(opts, XS_AUTH_BASE_URL);\r\n}\r\n\r\n/** Google-style sign-out popup on the Auth-Server domain. */\r\nexport function signOutWithXS(opts: SignOutWithXSOptions): Promise<SignOutWithXSResult> {\r\n const authBase = opts.authBaseUrl?.trim() || XS_AUTH_BASE_URL;\r\n return signOutWithXSInternal(opts, authBase);\r\n}\r\n\r\n/** Signed-in user profile from XS Auth. */\r\nexport interface XSAuthUser {\r\n email: string;\r\n firstName?: string;\r\n lastName?: string;\r\n}\r\n\r\nexport interface LoginWithXSOptions {\r\n /** Your app's public client id from Xino Solutions. */\r\n clientId: string;\r\n /** Must be on your XS Auth client's allowed domains list (normally `window.location.origin`). */\r\n parentOrigin?: string;\r\n /**\r\n * Sign-in timeout in ms. Defaults to 180s to allow MFA verification in the Auth-Server popup.\r\n */\r\n timeoutMs?: number;\r\n scope?: string;\r\n /**\r\n * Request a `nonce` inside `idToken` — your backend should verify it matches when validating the JWT.\r\n */\r\n useNonce?: boolean;\r\n /**\r\n * OAuth-style prompt for multi-account SSO on the Auth-Server domain.\r\n * - `none`: silent sign-in with the primary browser session (fails with `login_required` if absent)\r\n * - `select_account`: always show the account chooser when sessions exist\r\n * - `login`: force email/password (add another account)\r\n */\r\n prompt?: 'none' | 'select_account' | 'login';\r\n /** Prefer a specific XS Auth user id (`sub`) when continuing an existing browser session. */\r\n accountId?: string;\r\n /** When true and `prompt` is unset, defaults to `none` instead of account chooser. */\r\n preferPrimary?: boolean;\r\n /** Override Auth-Server base URL (e.g. same-origin `/xs-auth` proxy in local dev). */\r\n authBaseUrl?: string;\r\n}\r\n\r\nexport interface LoginWithXSResult {\r\n user: XSAuthUser;\r\n /** Short-lived signed JWT — send to your backend to create a session. */\r\n idToken: string;\r\n /** True when the user completed MFA during this sign-in (`amr` includes `mfa`). */\r\n mfaVerified: boolean;\r\n}\r\n\r\nfunction bytesBuffer(len: number): Uint8Array {\r\n const out = new Uint8Array(len);\r\n crypto.getRandomValues(out);\r\n return out;\r\n}\r\n\r\nfunction base64UrlEncode(buf: Uint8Array | ArrayBuffer): string {\r\n const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);\r\n let binary = '';\r\n const chunkSize = 0x8000;\r\n for (let i = 0; i < bytes.length; i += chunkSize) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\r\n }\r\n const b64 = btoa(binary);\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/u, '');\r\n}\r\n\r\nasync function pkceVerifierAndChallenge(): Promise<{\r\n verifier: string;\r\n challenge: string;\r\n}> {\r\n const verifier = base64UrlEncode(bytesBuffer(64));\r\n const data = new TextEncoder().encode(verifier);\r\n const digest = await crypto.subtle.digest('SHA-256', data);\r\n const challenge = base64UrlEncode(digest);\r\n return { verifier, challenge };\r\n}\r\n\r\n/** PKCE helpers for tests / custom callers. */\r\nexport async function createPkcePair(): Promise<{\r\n verifier: string;\r\n challenge: string;\r\n}> {\r\n return pkceVerifierAndChallenge();\r\n}\r\n\r\nconst STATE_KEY_STORAGE = '__xs_login_state';\r\n\r\nfunction parseSdkUser(raw: unknown): XSAuthUser | null {\r\n if (!raw || typeof raw !== 'object') return null;\r\n const u = raw as Record<string, unknown>;\r\n const email = typeof u.email === 'string' ? u.email.trim() : '';\r\n if (!email) return null;\r\n const user: XSAuthUser = { email };\r\n const firstName =\r\n typeof u.firstName === 'string' ? u.firstName.trim() : '';\r\n const lastName = typeof u.lastName === 'string' ? u.lastName.trim() : '';\r\n if (firstName) user.firstName = firstName;\r\n if (lastName) user.lastName = lastName;\r\n return user;\r\n}\r\n\r\nfunction resolvePrompt(opts: LoginWithXSOptions): string | undefined {\r\n if (opts.prompt) return opts.prompt;\r\n if (opts.preferPrimary) return 'none';\r\n return undefined;\r\n}\r\n\r\nfunction authPublicPathFromBase(authBaseUrl: string): string {\r\n try {\r\n const pathname = new URL(authBaseUrl).pathname.replace(/\\/$/u, '');\r\n return pathname === '/' ? '' : pathname;\r\n } catch {\r\n return '';\r\n }\r\n}\r\n\r\nfunction maybeSetPublicPath(params: URLSearchParams, authBaseUrl: string): void {\r\n const publicPath = authPublicPathFromBase(authBaseUrl);\r\n if (publicPath) params.set('public_path', publicPath);\r\n}\r\n\r\n/**\r\n * Opens the XS Auth sign-in popup and returns the signed-in user plus a verifiable `idToken`.\r\n *\r\n * All Auth-Server HTTP calls happen inside the popup (same origin). The host app only\r\n * opens the popup and exchanges postMessages with the PKCE verifier — no fetch to Auth-Server.\r\n */\r\nexport async function loginWithXS(\r\n opts: LoginWithXSOptions,\r\n): Promise<LoginWithXSResult> {\r\n const authBase = opts.authBaseUrl?.trim() || XS_AUTH_BASE_URL;\r\n const normalizedBase = normalizeBaseUrl(authBase);\r\n const authOrigin = normalizedBase.origin;\r\n const parentOrigin = (opts.parentOrigin ?? globalThis.location?.origin) as\r\n | string\r\n | undefined;\r\n if (!parentOrigin || typeof window === 'undefined') {\r\n throw new Error(\r\n 'loginWithXS requires a browser Window and explicit parentOrigin (or window.location).',\r\n );\r\n }\r\n\r\n const timeoutMs =\r\n opts.timeoutMs !== undefined ? opts.timeoutMs : 180_000;\r\n\r\n const state = randomBase64State();\r\n sessionStorage.setItem(STATE_KEY_STORAGE, state);\r\n\r\n const nonce = opts.useNonce ? randomBase64State() : undefined;\r\n const pair = await pkceVerifierAndChallenge();\r\n\r\n const params = new URLSearchParams({\r\n client_id: opts.clientId,\r\n state,\r\n code_challenge: pair.challenge,\r\n code_challenge_method: 'S256',\r\n parent_origin: parentOrigin,\r\n response_mode: 'popup',\r\n });\r\n if (opts.scope?.trim()) params.set('scope', opts.scope.trim());\r\n if (nonce) params.set('nonce', nonce);\r\n const prompt = resolvePrompt(opts);\r\n if (prompt) params.set('prompt', prompt);\r\n if (opts.accountId?.trim()) params.set('account_id', opts.accountId.trim());\r\n maybeSetPublicPath(params, authBase);\r\n\r\n const authorizeUrl = `${normalizedBase.href.replace(/\\/?$/u, '')}/authorize?${params.toString()}`;\r\n\r\n const popupWidth = prompt === 'none' ? 420 : 480;\r\n const popupHeight = prompt === 'none' ? 120 : 640;\r\n const popup = window.open(\r\n authorizeUrl,\r\n `xs-auth-${crypto.randomUUID()}`,\r\n popupWindowFeatures(popupWidth, popupHeight),\r\n );\r\n if (!popup) throw new PopupBlockedError();\r\n\r\n return await new Promise<LoginWithXSResult>((resolve, reject) => {\r\n let cleaned = false;\r\n const teardown = (): void => {\r\n if (cleaned) return;\r\n cleaned = true;\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n clearInterval(closePoll);\r\n clearTimeout(timer);\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n const fail = (e: unknown): void => {\r\n teardown();\r\n reject(e instanceof Error ? e : new Error(String(e)));\r\n };\r\n\r\n const timer = window.setTimeout(() => {\r\n fail(new LoginTimeoutError());\r\n }, timeoutMs);\r\n\r\n const handleMessage = (event: MessageEvent): void => {\r\n if (event.origin !== authOrigin) return;\r\n const d = event.data as Partial<Record<string, unknown>>;\r\n if (d?.source !== 'xs-auth') return;\r\n\r\n const st = typeof d.state === 'string' ? d.state : '';\r\n if (!st || st !== sessionStorage.getItem(STATE_KEY_STORAGE)) return;\r\n\r\n if (typeof d.error === 'string' && d.error.length > 0) {\r\n teardown();\r\n reject(\r\n new XSAuthDeniedError(\r\n String(d.error),\r\n typeof d.error_description === 'string'\r\n ? d.error_description\r\n : '',\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n if (d.type === 'need_verifier') {\r\n try {\r\n popup.postMessage(\r\n {\r\n source: 'xs-auth-opener',\r\n state: st,\r\n code_verifier: pair.verifier,\r\n client_id: opts.clientId,\r\n },\r\n authOrigin,\r\n );\r\n } catch {\r\n fail(new XSAuthDeniedError('exchange_failed', 'Sign in could not be completed.'));\r\n }\r\n return;\r\n }\r\n\r\n const idToken =\r\n typeof d.id_token === 'string'\r\n ? d.id_token\r\n : typeof d.idToken === 'string'\r\n ? d.idToken\r\n : '';\r\n const user = parseSdkUser(d.user);\r\n if (!idToken || !user) return;\r\n\r\n sessionStorage.removeItem(STATE_KEY_STORAGE);\r\n clearTimeout(timer);\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n clearInterval(closePoll);\r\n cleaned = true;\r\n\r\n resolve({ user, idToken, mfaVerified: idTokenIncludesMfa(idToken) });\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage as EventListener);\r\n\r\n const closePoll = window.setInterval(() => {\r\n if (!popup.closed) return;\r\n if (cleaned) return;\r\n const pending = sessionStorage.getItem(STATE_KEY_STORAGE);\r\n if (!pending) return;\r\n fail(new PopupClosedError());\r\n }, 280);\r\n });\r\n}\r\n\r\n/** True when an XS Auth idToken indicates MFA was completed at sign-in. */\r\nexport function idTokenIncludesMfa(idToken: string): boolean {\r\n const amr = parseIdTokenAmr(idToken);\r\n return Array.isArray(amr) && amr.includes('mfa');\r\n}\r\n\r\n/** Read the `amr` claim from an XS Auth idToken payload (no signature verification). */\r\nexport function parseIdTokenAmr(idToken: string): string[] | null {\r\n const payload = parseJwtPayload(idToken);\r\n if (!payload || !('amr' in payload)) return null;\r\n const amr = payload.amr;\r\n if (Array.isArray(amr)) {\r\n return amr.filter((v): v is string => typeof v === 'string');\r\n }\r\n if (typeof amr === 'string' && amr.trim()) return [amr.trim()];\r\n return null;\r\n}\r\n\r\nfunction parseJwtPayload(token: string): Record<string, unknown> | null {\r\n const parts = token.split('.');\r\n if (parts.length < 2) return null;\r\n try {\r\n const json = atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'));\r\n const parsed: unknown = JSON.parse(json);\r\n return parsed && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction randomBase64State(): string {\r\n return base64UrlEncode(bytesBuffer(32));\r\n}\r\n\r\nfunction normalizeBaseUrl(s: string): URL {\r\n return new URL(s);\r\n}\r\n\r\n/** Center popup over the opener window (falls back to screen center). */\r\nfunction popupWindowFeatures(width: number, height: number): string {\r\n const win = window;\r\n const outerW = win.outerWidth > 0 ? win.outerWidth : win.innerWidth;\r\n const outerH = win.outerHeight > 0 ? win.outerHeight : win.innerHeight;\r\n const screenX = win.screenX ?? win.screenLeft ?? 0;\r\n const screenY = win.screenY ?? win.screenTop ?? 0;\r\n const left = Math.round(screenX + Math.max(0, (outerW - width) / 2));\r\n const top = Math.round(screenY + Math.max(0, (outerH - height) / 2));\r\n return `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;\r\n}\r\n\r\n/** True when Auth-Server has no active browser session for silent sign-in. */\r\nexport function isLoginRequiredError(error: unknown): boolean {\r\n return error instanceof XSAuthDeniedError && error.errorCode === 'login_required';\r\n}\r\n","/** Popup was blocked by the browser or environment. */\r\nexport class PopupBlockedError extends Error {\r\n readonly name = 'PopupBlockedError';\r\n}\r\n\r\n/** User closed the popup before completing login. */\r\nexport class PopupClosedError extends Error {\r\n readonly name = 'PopupClosedError';\r\n}\r\n\r\n/** XS Auth popup did not complete within timeout. */\r\nexport class LoginTimeoutError extends Error {\r\n readonly name = 'LoginTimeoutError';\r\n}\r\n\r\n/** XS Auth returned an OAuth-style error inside postMessage. */\r\nexport class XSAuthDeniedError extends Error {\r\n readonly name = 'XSAuthDeniedError';\r\n readonly errorCode: string;\r\n readonly description: string;\r\n\r\n constructor(errorCode: string, description: string) {\r\n super(description || errorCode || 'xs_auth_denied');\r\n this.errorCode = errorCode;\r\n this.description = description;\r\n }\r\n}\r\n\r\n/** Session bridge did not respond within timeout. */\r\nexport class LoginBridgeTimeoutError extends Error {\r\n readonly name = 'LoginBridgeTimeoutError';\r\n}\r\n","import {\r\n LoginBridgeTimeoutError,\r\n PopupBlockedError,\r\n PopupClosedError,\r\n} from './errors';\r\n\r\n/** XS Auth browser session account (multi-account SSO on the Auth-Server domain). */\r\nexport interface XSBrowserAccount {\r\n sessionId: string;\r\n userId: string;\r\n email: string;\r\n name: string;\r\n isPrimary: boolean;\r\n}\r\n\r\nexport interface OpenSessionBridgeOptions {\r\n clientId: string;\r\n parentOrigin?: string;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport interface SessionBridge {\r\n listAccounts(): Promise<XSBrowserAccount[]>;\r\n revokeAccount(sessionId: string): Promise<{ accounts: XSBrowserAccount[]; remainingCount: number }>;\r\n revokeAll(): Promise<void>;\r\n setPrimary(sessionId: string): Promise<XSBrowserAccount[]>;\r\n close(): void;\r\n}\r\n\r\nexport class SessionBridgeError extends Error {\r\n readonly name = 'SessionBridgeError';\r\n readonly errorCode: string;\r\n\r\n constructor(errorCode: string, message: string) {\r\n super(message || errorCode);\r\n this.errorCode = errorCode;\r\n }\r\n}\r\n\r\ntype BridgeMessage = Partial<Record<string, unknown>>;\r\n\r\nconst BRIDGE_STATE_KEY = '__xs_bridge_state';\r\n\r\nfunction parseAccounts(raw: unknown): XSBrowserAccount[] {\r\n if (!Array.isArray(raw)) return [];\r\n return raw\r\n .map((item) => {\r\n if (!item || typeof item !== 'object') return null;\r\n const row = item as Record<string, unknown>;\r\n const sessionId =\r\n typeof row.sessionId === 'string'\r\n ? row.sessionId\r\n : typeof row.session_id === 'string'\r\n ? row.session_id\r\n : '';\r\n const userId =\r\n typeof row.userId === 'string'\r\n ? row.userId\r\n : typeof row.user_id === 'string'\r\n ? row.user_id\r\n : '';\r\n const email = typeof row.email === 'string' ? row.email : '';\r\n const name = typeof row.name === 'string' ? row.name : email;\r\n if (!sessionId || !email) return null;\r\n return {\r\n sessionId,\r\n userId,\r\n email,\r\n name,\r\n isPrimary: row.isPrimary === true || row.is_primary === true,\r\n };\r\n })\r\n .filter((x): x is XSBrowserAccount => x !== null);\r\n}\r\n\r\nfunction hiddenBridgePopupFeatures(): string {\r\n return 'width=1,height=1,left=-10000,top=-10000,resizable=no,scrollbars=no';\r\n}\r\n\r\nfunction randomBridgeState(): string {\r\n const bytes = new Uint8Array(32);\r\n crypto.getRandomValues(bytes);\r\n let binary = '';\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i]!);\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/u, '');\r\n}\r\n\r\n/**\r\n * Opens a same-origin Auth-Server popup bridge so the host app can list and revoke\r\n * browser SSO sessions without cross-origin cookie access.\r\n */\r\nexport async function openSessionBridge(\r\n opts: OpenSessionBridgeOptions,\r\n authBaseUrl: string,\r\n): Promise<SessionBridge> {\r\n const parentOrigin = (opts.parentOrigin ?? globalThis.location?.origin) as string | undefined;\r\n if (!parentOrigin || typeof window === 'undefined') {\r\n throw new Error(\r\n 'openSessionBridge requires a browser Window and explicit parentOrigin (or window.location).',\r\n );\r\n }\r\n\r\n const normalizedBase = new URL(authBaseUrl);\r\n const authOrigin = normalizedBase.origin;\r\n const state = randomBridgeState();\r\n sessionStorage.setItem(BRIDGE_STATE_KEY, state);\r\n\r\n const params = new URLSearchParams({\r\n client_id: opts.clientId,\r\n parent_origin: parentOrigin,\r\n state,\r\n });\r\n\r\n const bridgeUrl = `${normalizedBase.href.replace(/\\/?$/u, '')}/session/bridge?${params.toString()}`;\r\n const popup = window.open(\r\n bridgeUrl,\r\n `xs-auth-bridge-${crypto.randomUUID()}`,\r\n hiddenBridgePopupFeatures(),\r\n );\r\n if (!popup) throw new PopupBlockedError();\r\n\r\n const timeoutMs = opts.timeoutMs !== undefined ? opts.timeoutMs : 120_000;\r\n let cleaned = false;\r\n let closePoll: ReturnType<typeof setInterval> | undefined;\r\n\r\n const teardown = (): void => {\r\n if (cleaned) return;\r\n cleaned = true;\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n if (closePoll !== undefined) clearInterval(closePoll);\r\n sessionStorage.removeItem(BRIDGE_STATE_KEY);\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n const pending = new Map<\r\n string,\r\n {\r\n resolve: (value: BridgeMessage) => void;\r\n reject: (error: Error) => void;\r\n }\r\n >();\r\n\r\n let bridgeReady = false;\r\n let readyResolve: (() => void) | null = null;\r\n let readyReject: ((error: Error) => void) | null = null;\r\n\r\n const readyPromise = new Promise<void>((resolve, reject) => {\r\n readyResolve = resolve;\r\n readyReject = reject;\r\n });\r\n\r\n const handleMessage = (event: MessageEvent): void => {\r\n if (event.origin !== authOrigin) return;\r\n const d = event.data as BridgeMessage;\r\n if (d?.source !== 'xs-auth') return;\r\n\r\n const st = typeof d.state === 'string' ? d.state : '';\r\n if (!st || st !== sessionStorage.getItem(BRIDGE_STATE_KEY)) return;\r\n\r\n if (d.type === 'bridge_ready') {\r\n bridgeReady = true;\r\n readyResolve?.();\r\n return;\r\n }\r\n\r\n const requestId = typeof d.requestId === 'string' ? d.requestId : '';\r\n if (!requestId) return;\r\n\r\n const entry = pending.get(requestId);\r\n if (!entry) return;\r\n\r\n pending.delete(requestId);\r\n\r\n if (typeof d.error === 'string' && d.error.length > 0) {\r\n entry.reject(\r\n new SessionBridgeError(\r\n String(d.error),\r\n typeof d.error_description === 'string' ? d.error_description : '',\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n if (d.type === 'result') {\r\n entry.resolve(d);\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage as EventListener);\r\n\r\n closePoll = window.setInterval(() => {\r\n if (!popup.closed) return;\r\n if (cleaned) return;\r\n for (const [, entry] of pending) {\r\n entry.reject(new PopupClosedError());\r\n }\r\n pending.clear();\r\n readyReject?.(new PopupClosedError());\r\n teardown();\r\n }, 280);\r\n\r\n const readyTimer = window.setTimeout(() => {\r\n if (bridgeReady) return;\r\n readyReject?.(new LoginBridgeTimeoutError());\r\n teardown();\r\n }, timeoutMs);\r\n\r\n try {\r\n await readyPromise;\r\n } catch (error) {\r\n clearTimeout(readyTimer);\r\n throw error;\r\n }\r\n clearTimeout(readyTimer);\r\n\r\n const sendRequest = (type: string, extra: Record<string, unknown> = {}): Promise<BridgeMessage> => {\r\n if (popup.closed) {\r\n return Promise.reject(new PopupClosedError());\r\n }\r\n\r\n const requestId = crypto.randomUUID();\r\n return new Promise<BridgeMessage>((resolve, reject) => {\r\n const timer = window.setTimeout(() => {\r\n pending.delete(requestId);\r\n reject(new LoginBridgeTimeoutError());\r\n }, timeoutMs);\r\n\r\n pending.set(requestId, {\r\n resolve: (value) => {\r\n clearTimeout(timer);\r\n resolve(value);\r\n },\r\n reject: (error) => {\r\n clearTimeout(timer);\r\n reject(error);\r\n },\r\n });\r\n\r\n try {\r\n popup.postMessage(\r\n {\r\n source: 'xs-auth-opener',\r\n state,\r\n client_id: opts.clientId,\r\n requestId,\r\n type,\r\n ...extra,\r\n },\r\n authOrigin,\r\n );\r\n } catch {\r\n pending.delete(requestId);\r\n clearTimeout(timer);\r\n reject(new SessionBridgeError('post_message_failed', 'Could not reach the session bridge.'));\r\n }\r\n });\r\n };\r\n\r\n return {\r\n async listAccounts() {\r\n const result = await sendRequest('list_accounts');\r\n return parseAccounts(result.accounts);\r\n },\r\n\r\n async revokeAccount(sessionId: string) {\r\n const result = await sendRequest('revoke', { session_id: sessionId.trim() });\r\n const accounts = parseAccounts(result.accounts);\r\n const remainingCount =\r\n typeof result.remainingCount === 'number' ? result.remainingCount : accounts.length;\r\n return { accounts, remainingCount };\r\n },\r\n\r\n async revokeAll() {\r\n await sendRequest('revoke_all');\r\n },\r\n\r\n async setPrimary(sessionId: string) {\r\n const result = await sendRequest('set_primary', { session_id: sessionId.trim() });\r\n return parseAccounts(result.accounts);\r\n },\r\n\r\n close() {\r\n teardown();\r\n },\r\n };\r\n}\r\n\r\n/** True when the user must pick another primary account before signing out. */\r\nexport function isPrimaryAccountError(error: unknown): boolean {\r\n return error instanceof SessionBridgeError && error.errorCode === 'primary_account';\r\n}\r\n","import {\r\n LoginBridgeTimeoutError,\r\n PopupBlockedError,\r\n PopupClosedError,\r\n} from './errors';\r\n\r\nexport interface SignOutWithXSOptions {\r\n clientId: string;\r\n parentOrigin?: string;\r\n /** XS Auth user id (`sub`) for the account active in the host app. */\r\n activeUserId?: string;\r\n timeoutMs?: number;\r\n /** Override Auth-Server base URL (e.g. same-origin `/xs-auth` proxy in local dev). */\r\n authBaseUrl?: string;\r\n}\r\n\r\nexport type SignOutAction = 'revoked_one' | 'revoked_all' | 'cancelled';\r\n\r\nexport interface SignOutWithXSResult {\r\n action: SignOutAction;\r\n revokedCurrent: boolean;\r\n remainingCount: number;\r\n}\r\n\r\nconst SIGN_OUT_STATE_KEY = '__xs_sign_out_state';\r\n\r\nfunction popupWindowFeatures(width: number, height: number): string {\r\n const win = window;\r\n const outerW = win.outerWidth > 0 ? win.outerWidth : win.innerWidth;\r\n const outerH = win.outerHeight > 0 ? win.outerHeight : win.innerHeight;\r\n const screenX = win.screenX ?? win.screenLeft ?? 0;\r\n const screenY = win.screenY ?? win.screenTop ?? 0;\r\n const left = Math.round(screenX + Math.max(0, (outerW - width) / 2));\r\n const top = Math.round(screenY + Math.max(0, (outerH - height) / 2));\r\n return `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;\r\n}\r\n\r\nfunction randomState(): string {\r\n const bytes = new Uint8Array(32);\r\n crypto.getRandomValues(bytes);\r\n let binary = '';\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i]!);\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/u, '');\r\n}\r\n\r\nfunction parseSignOutResult(raw: SignOutAction, data: Record<string, unknown>): SignOutWithXSResult {\r\n return {\r\n action: raw,\r\n revokedCurrent: data.revokedCurrent === true,\r\n remainingCount:\r\n typeof data.remainingCount === 'number' && Number.isFinite(data.remainingCount)\r\n ? Math.max(0, data.remainingCount)\r\n : 0,\r\n };\r\n}\r\n\r\n/**\r\n * Opens a centered XS Auth popup to sign out of one or all browser SSO accounts\r\n * (Google-style account manager on the Auth-Server domain).\r\n */\r\nexport async function signOutWithXS(\r\n opts: SignOutWithXSOptions,\r\n authBaseUrl: string,\r\n): Promise<SignOutWithXSResult> {\r\n const parentOrigin = (opts.parentOrigin ?? globalThis.location?.origin) as string | undefined;\r\n if (!parentOrigin || typeof window === 'undefined') {\r\n throw new Error(\r\n 'signOutWithXS requires a browser Window and explicit parentOrigin (or window.location).',\r\n );\r\n }\r\n\r\n const normalizedBase = new URL(authBaseUrl);\r\n const authOrigin = normalizedBase.origin;\r\n const state = randomState();\r\n sessionStorage.setItem(SIGN_OUT_STATE_KEY, state);\r\n\r\n const params = new URLSearchParams({\r\n client_id: opts.clientId,\r\n parent_origin: parentOrigin,\r\n state,\r\n });\r\n if (opts.activeUserId?.trim()) {\r\n params.set('active_user_id', opts.activeUserId.trim());\r\n }\r\n\r\n const url = `${normalizedBase.href.replace(/\\/?$/u, '')}/session/sign-out?${params.toString()}`;\r\n const popup = window.open(\r\n url,\r\n `xs-auth-signout-${crypto.randomUUID()}`,\r\n popupWindowFeatures(480, 640),\r\n );\r\n if (!popup) throw new PopupBlockedError();\r\n\r\n const timeoutMs = opts.timeoutMs !== undefined ? opts.timeoutMs : 120_000;\r\n\r\n return await new Promise<SignOutWithXSResult>((resolve, reject) => {\r\n let cleaned = false;\r\n\r\n const teardown = (): void => {\r\n if (cleaned) return;\r\n cleaned = true;\r\n window.removeEventListener('message', handleMessage as EventListener);\r\n clearInterval(closePoll);\r\n clearTimeout(timer);\r\n sessionStorage.removeItem(SIGN_OUT_STATE_KEY);\r\n try {\r\n popup.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n\r\n const fail = (error: Error): void => {\r\n teardown();\r\n reject(error);\r\n };\r\n\r\n const timer = window.setTimeout(() => {\r\n fail(new LoginBridgeTimeoutError());\r\n }, timeoutMs);\r\n\r\n const handleMessage = (event: MessageEvent): void => {\r\n if (event.origin !== authOrigin) return;\r\n const d = event.data as Partial<Record<string, unknown>>;\r\n if (d?.source !== 'xs-auth') return;\r\n\r\n const st = typeof d.state === 'string' ? d.state : '';\r\n if (!st || st !== sessionStorage.getItem(SIGN_OUT_STATE_KEY)) return;\r\n\r\n if (d.type === 'sign_out_cancelled') {\r\n teardown();\r\n resolve(parseSignOutResult('cancelled', d));\r\n return;\r\n }\r\n\r\n if (d.type === 'sign_out_complete') {\r\n teardown();\r\n const actionRaw = typeof d.action === 'string' ? d.action : 'revoked_one';\r\n const action: SignOutAction =\r\n actionRaw === 'revoked_all'\r\n ? 'revoked_all'\r\n : actionRaw === 'cancelled'\r\n ? 'cancelled'\r\n : 'revoked_one';\r\n resolve(parseSignOutResult(action, d));\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage as EventListener);\r\n\r\n const closePoll = window.setInterval(() => {\r\n if (!popup.closed) return;\r\n if (cleaned) return;\r\n if (!sessionStorage.getItem(SIGN_OUT_STATE_KEY)) return;\r\n fail(new PopupClosedError());\r\n }, 280);\r\n });\r\n}\r\n"],"mappings":"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","names":["openSessionBridge","signOutWithXS","openSessionBridge","signOutWithXS","popupWindowFeatures"]}