@bigso/auth-sdk 0.4.7 → 0.5.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.
@@ -1,376 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/browser/index.ts
21
- var browser_exports = {};
22
- __export(browser_exports, {
23
- BigsoAuth: () => BigsoAuth
24
- });
25
- module.exports = __toCommonJS(browser_exports);
26
-
27
- // src/utils/crypto.ts
28
- async function sha256Base64Url(input) {
29
- const encoder = new TextEncoder();
30
- const data = encoder.encode(input);
31
- const digest = await crypto.subtle.digest("SHA-256", data);
32
- return base64Url(new Uint8Array(digest));
33
- }
34
- function generateVerifier(length = 32) {
35
- const array = new Uint8Array(length);
36
- crypto.getRandomValues(array);
37
- return base64Url(array);
38
- }
39
- function base64Url(bytes) {
40
- return btoa(String.fromCharCode(...bytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
41
- }
42
- function generateRandomId() {
43
- return crypto.randomUUID();
44
- }
45
-
46
- // src/utils/events.ts
47
- var EventEmitter = class {
48
- constructor() {
49
- this.events = {};
50
- }
51
- on(event, handler) {
52
- if (!this.events[event]) this.events[event] = [];
53
- this.events[event].push(handler);
54
- }
55
- off(event, handler) {
56
- if (!this.events[event]) return;
57
- this.events[event] = this.events[event].filter((h) => h !== handler);
58
- }
59
- emit(event, data) {
60
- this.events[event]?.forEach((fn) => fn(data));
61
- }
62
- };
63
-
64
- // src/utils/jws.ts
65
- var import_jose = require("jose");
66
- async function verifySignedPayload(token, jwksUrl, expectedAudience) {
67
- const JWKS = (0, import_jose.createRemoteJWKSet)(new URL(jwksUrl));
68
- const { payload } = await (0, import_jose.jwtVerify)(token, JWKS, {
69
- audience: expectedAudience
70
- });
71
- return payload;
72
- }
73
-
74
- // src/browser/auth.ts
75
- var BigsoAuth = class extends EventEmitter {
76
- constructor(options) {
77
- super();
78
- this.authCompleted = false;
79
- this.requestId = generateRandomId();
80
- this.loginInProgress = false;
81
- this.options = {
82
- timeout: 5e3,
83
- // por defecto 5s (estándar v2.3)
84
- debug: false,
85
- redirectUri: "",
86
- tenantHint: "",
87
- theme: "light",
88
- ...options
89
- };
90
- }
91
- /**
92
- * Inicia el flujo de autenticación.
93
- * @returns Promise que resuelve con el payload decodificado del JWS (solo para información; el backend debe validar)
94
- */
95
- async login() {
96
- if (this.loginInProgress) {
97
- this.debug("login() ya en curso, ignorando llamada duplicada");
98
- return Promise.reject(new Error("Login already in progress"));
99
- }
100
- this.loginInProgress = true;
101
- this.authCompleted = false;
102
- const state = generateRandomId();
103
- const nonce = generateRandomId();
104
- const verifier = generateVerifier();
105
- const requestId = this.requestId;
106
- sessionStorage.setItem("sso_ctx", JSON.stringify({ state, nonce, verifier, requestId }));
107
- this.createUI();
108
- return new Promise((resolve, reject) => {
109
- this.abortController = new AbortController();
110
- const { signal } = this.abortController;
111
- const cleanup = () => {
112
- if (this.timeoutId) clearTimeout(this.timeoutId);
113
- if (this.messageListener) window.removeEventListener("message", this.messageListener);
114
- this.iframe?.remove();
115
- this.iframe = void 0;
116
- this.authCompleted = true;
117
- this.loginInProgress = false;
118
- };
119
- this.messageListener = async (event) => {
120
- if (event.origin !== this.options.ssoOrigin) {
121
- this.debug("Ignorado mensaje de origen no autorizado:", event.origin);
122
- return;
123
- }
124
- const msg = event.data;
125
- this.debug("Mensaje recibido:", msg);
126
- if (msg.requestId && msg.requestId !== requestId) {
127
- this.debug("requestId no coincide, ignorado");
128
- return;
129
- }
130
- if (msg.type === "sso-ready") {
131
- this.debug("sso-ready recibido, iniciando timeout y enviando sso-init");
132
- this.timeoutId = window.setTimeout(() => {
133
- if (!this.authCompleted) {
134
- this.debug("Timeout alcanzado, activando fallback");
135
- this.closeUI();
136
- cleanup();
137
- this.emit("fallback");
138
- window.location.href = this.buildFallbackUrl();
139
- reject(new Error("Timeout"));
140
- }
141
- }, this.options.timeout);
142
- const codeChallenge = await sha256Base64Url(verifier);
143
- const initPayload = {
144
- state,
145
- nonce,
146
- code_challenge: codeChallenge,
147
- code_challenge_method: "S256",
148
- origin: window.location.origin,
149
- ...this.options.redirectUri && { redirect_uri: this.options.redirectUri },
150
- ...this.options.tenantHint && { tenant_hint: this.options.tenantHint },
151
- timeout_ms: this.options.timeout
152
- // pasar el timeout configurado (opcional)
153
- };
154
- this.iframe?.contentWindow?.postMessage({
155
- v: "2.3",
156
- // versión del protocolo (estándar v2.3)
157
- source: "@app/widget",
158
- type: "sso-init",
159
- requestId: this.requestId,
160
- payload: initPayload
161
- }, this.options.ssoOrigin);
162
- this.emit("ready");
163
- return;
164
- }
165
- if (msg.type === "sso-success") {
166
- this.debug("sso-success recibido");
167
- clearTimeout(this.timeoutId);
168
- try {
169
- const payload = msg.payload;
170
- const ctx = JSON.parse(sessionStorage.getItem("sso_ctx") || "{}");
171
- if (payload.state !== ctx.state) {
172
- throw new Error("Invalid state");
173
- }
174
- const decoded = await verifySignedPayload(
175
- payload.signed_payload,
176
- this.options.jwksUrl,
177
- window.location.origin
178
- // aud esperado
179
- );
180
- if (decoded.nonce !== ctx.nonce) {
181
- throw new Error("Invalid nonce");
182
- }
183
- this.debug("JWS v\xE1lido, payload:", decoded);
184
- this.closeUI();
185
- cleanup();
186
- const result = {
187
- ...decoded,
188
- signed_payload: payload.signed_payload
189
- };
190
- this.emit("success", result);
191
- resolve(result);
192
- } catch (err) {
193
- this.debug("Error en sso-success:", err);
194
- this.closeUI();
195
- cleanup();
196
- this.emit("error", err);
197
- reject(err);
198
- }
199
- return;
200
- }
201
- if (msg.type === "sso-error") {
202
- const errorPayload = msg.payload;
203
- this.debug("sso-error recibido:", errorPayload);
204
- clearTimeout(this.timeoutId);
205
- this.closeUI();
206
- cleanup();
207
- if (errorPayload.code === "version_mismatch") {
208
- this.emit("error", errorPayload);
209
- window.location.href = this.buildFallbackUrl();
210
- reject(new Error(`Version mismatch: expected ${errorPayload.expected_version}`));
211
- } else {
212
- this.emit("error", errorPayload);
213
- reject(errorPayload);
214
- }
215
- }
216
- if (msg.type === "sso-close") {
217
- this.debug("sso-close recibido");
218
- this.closeUI();
219
- cleanup();
220
- reject(new Error("Login cancelled by user"));
221
- }
222
- };
223
- window.addEventListener("message", this.messageListener);
224
- signal.addEventListener("abort", () => {
225
- this.debug("Operaci\xF3n abortada");
226
- this.closeUI();
227
- cleanup();
228
- reject(new Error("Login aborted"));
229
- });
230
- });
231
- }
232
- /** Cancela el flujo de autenticación en curso */
233
- abort() {
234
- this.abortController?.abort();
235
- }
236
- // ─── UI Management ───────────────────────────────────────────────
237
- /**
238
- * Crea (o reutiliza) el overlay con Shadow DOM y el iframe visible.
239
- * Patrón tomado del CDN widget v1: Shadow DOM para aislar estilos.
240
- */
241
- createUI() {
242
- if (!this.hostEl) {
243
- this.hostEl = document.createElement("div");
244
- this.hostEl.id = "bigso-auth-host";
245
- this.shadowRoot = this.hostEl.attachShadow({ mode: "open" });
246
- const style = document.createElement("style");
247
- style.textContent = this.getOverlayStyles();
248
- this.shadowRoot.appendChild(style);
249
- this.overlayEl = document.createElement("div");
250
- this.overlayEl.className = "sso-overlay";
251
- const closeBtn = document.createElement("button");
252
- closeBtn.className = "sso-close-btn";
253
- closeBtn.innerHTML = "×";
254
- closeBtn.setAttribute("aria-label", "Cerrar modal");
255
- closeBtn.addEventListener("click", () => this.abort());
256
- this.overlayEl.appendChild(closeBtn);
257
- this.overlayEl.addEventListener("click", (event) => {
258
- if (event.target === this.overlayEl) {
259
- this.abort();
260
- }
261
- });
262
- this.shadowRoot.appendChild(this.overlayEl);
263
- document.body.appendChild(this.hostEl);
264
- }
265
- this.iframe = document.createElement("iframe");
266
- this.iframe.className = "sso-frame";
267
- this.iframe.src = `${this.options.ssoOrigin}/auth/sign-in?v=2.3&client_id=${this.options.clientId}`;
268
- this.iframe.setAttribute("title", "SSO Login");
269
- this.overlayEl.appendChild(this.iframe);
270
- this.debug("Iframe creado", this.iframe.src);
271
- this.overlayEl.classList.remove("sso-closing");
272
- this.overlayEl.style.display = "flex";
273
- }
274
- /**
275
- * Cierra el overlay con animación suave (fadeOut + slideDown).
276
- * El overlay persiste en el DOM (solo se oculta).
277
- */
278
- closeUI() {
279
- if (!this.overlayEl || this.overlayEl.style.display === "none") return;
280
- this.overlayEl.classList.add("sso-closing");
281
- setTimeout(() => {
282
- if (this.overlayEl) {
283
- this.overlayEl.style.display = "none";
284
- this.overlayEl.classList.remove("sso-closing");
285
- }
286
- }, 200);
287
- }
288
- /**
289
- * Estilos CSS encapsulados dentro del Shadow DOM.
290
- * Migrados del widget CDN v1 con las mismas animaciones y responsive.
291
- */
292
- getOverlayStyles() {
293
- return `
294
- .sso-overlay {
295
- position: fixed;
296
- inset: 0;
297
- display: none;
298
- justify-content: center;
299
- align-items: center;
300
- background: rgba(0, 0, 0, 0.6);
301
- z-index: 999999;
302
- backdrop-filter: blur(4px);
303
- -webkit-backdrop-filter: blur(4px);
304
- animation: fadeIn 0.2s ease;
305
- }
306
- .sso-frame {
307
- width: 370px;
308
- height: 350px;
309
- border: none;
310
- border-radius: 16px;
311
- background: var(--card-bg, #fff);
312
- box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
313
- animation: slideUp 0.3s ease;
314
- }
315
- @media (max-width: 480px), (max-height: 480px) {
316
- .sso-frame {
317
- width: 100%;
318
- height: 100%;
319
- border-radius: 0;
320
- }
321
- }
322
- .sso-close-btn {
323
- position: absolute;
324
- top: 12px;
325
- right: 12px;
326
- width: 32px;
327
- height: 32px;
328
- background: rgba(0, 0, 0, 0.4);
329
- color: white;
330
- border: none;
331
- border-radius: 50%;
332
- font-size: 24px;
333
- line-height: 1;
334
- cursor: pointer;
335
- display: flex;
336
- align-items: center;
337
- justify-content: center;
338
- z-index: 1000000;
339
- transition: background 0.2s;
340
- }
341
- .sso-close-btn:hover {
342
- background: rgba(0, 0, 0, 0.8);
343
- }
344
- .sso-overlay.sso-closing {
345
- animation: fadeOut 0.2s ease forwards;
346
- }
347
- .sso-overlay.sso-closing .sso-frame {
348
- animation: slideDown 0.2s ease forwards;
349
- }
350
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
351
- @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
352
- @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
353
- @keyframes slideDown { from { transform: translateY(0); opacity: 1; } to { transform: translateY(20px); opacity: 0; } }
354
- `;
355
- }
356
- // ─── Helpers ──────────────────────────────────────────────────────
357
- buildFallbackUrl() {
358
- const url = new URL(this.options.ssoOrigin);
359
- url.searchParams.set("app_id", this.options.clientId);
360
- url.searchParams.set("redirect_uri", this.options.redirectUri || window.location.origin);
361
- url.searchParams.set("response_type", "code");
362
- url.searchParams.set("state", generateRandomId());
363
- url.searchParams.set("code_challenge_method", "S256");
364
- url.searchParams.set("client_id", this.options.clientId);
365
- return url.toString();
366
- }
367
- debug(...args) {
368
- if (this.options.debug) {
369
- console.log("[BigsoAuth]", ...args);
370
- }
371
- }
372
- };
373
- // Annotate the CommonJS export names for ESM import in node:
374
- 0 && (module.exports = {
375
- BigsoAuth
376
- });
@@ -1,49 +0,0 @@
1
- import { B as BigsoAuthOptions } from '../types-CoXgtTry.cjs';
2
-
3
- declare class EventEmitter {
4
- private events;
5
- on(event: string, handler: Function): void;
6
- off(event: string, handler: Function): void;
7
- emit(event: string, data?: any): void;
8
- }
9
-
10
- declare class BigsoAuth extends EventEmitter {
11
- private options;
12
- private iframe?;
13
- private authCompleted;
14
- private requestId;
15
- private timeoutId?;
16
- private messageListener?;
17
- private abortController?;
18
- private hostEl?;
19
- private shadowRoot?;
20
- private overlayEl?;
21
- private loginInProgress;
22
- constructor(options: BigsoAuthOptions);
23
- /**
24
- * Inicia el flujo de autenticación.
25
- * @returns Promise que resuelve con el payload decodificado del JWS (solo para información; el backend debe validar)
26
- */
27
- login(): Promise<any>;
28
- /** Cancela el flujo de autenticación en curso */
29
- abort(): void;
30
- /**
31
- * Crea (o reutiliza) el overlay con Shadow DOM y el iframe visible.
32
- * Patrón tomado del CDN widget v1: Shadow DOM para aislar estilos.
33
- */
34
- private createUI;
35
- /**
36
- * Cierra el overlay con animación suave (fadeOut + slideDown).
37
- * El overlay persiste en el DOM (solo se oculta).
38
- */
39
- private closeUI;
40
- /**
41
- * Estilos CSS encapsulados dentro del Shadow DOM.
42
- * Migrados del widget CDN v1 con las mismas animaciones y responsive.
43
- */
44
- private getOverlayStyles;
45
- private buildFallbackUrl;
46
- private debug;
47
- }
48
-
49
- export { BigsoAuth, BigsoAuthOptions };
@@ -1,49 +0,0 @@
1
- import { B as BigsoAuthOptions } from '../types-CoXgtTry.js';
2
-
3
- declare class EventEmitter {
4
- private events;
5
- on(event: string, handler: Function): void;
6
- off(event: string, handler: Function): void;
7
- emit(event: string, data?: any): void;
8
- }
9
-
10
- declare class BigsoAuth extends EventEmitter {
11
- private options;
12
- private iframe?;
13
- private authCompleted;
14
- private requestId;
15
- private timeoutId?;
16
- private messageListener?;
17
- private abortController?;
18
- private hostEl?;
19
- private shadowRoot?;
20
- private overlayEl?;
21
- private loginInProgress;
22
- constructor(options: BigsoAuthOptions);
23
- /**
24
- * Inicia el flujo de autenticación.
25
- * @returns Promise que resuelve con el payload decodificado del JWS (solo para información; el backend debe validar)
26
- */
27
- login(): Promise<any>;
28
- /** Cancela el flujo de autenticación en curso */
29
- abort(): void;
30
- /**
31
- * Crea (o reutiliza) el overlay con Shadow DOM y el iframe visible.
32
- * Patrón tomado del CDN widget v1: Shadow DOM para aislar estilos.
33
- */
34
- private createUI;
35
- /**
36
- * Cierra el overlay con animación suave (fadeOut + slideDown).
37
- * El overlay persiste en el DOM (solo se oculta).
38
- */
39
- private closeUI;
40
- /**
41
- * Estilos CSS encapsulados dentro del Shadow DOM.
42
- * Migrados del widget CDN v1 con las mismas animaciones y responsive.
43
- */
44
- private getOverlayStyles;
45
- private buildFallbackUrl;
46
- private debug;
47
- }
48
-
49
- export { BigsoAuth, BigsoAuthOptions };