@bigso/auth-sdk 0.5.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigso/auth-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "SDK de autenticación para SSO v2 - JWT Bearer + PKCE",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -1,364 +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
- debug: false,
84
- redirectUri: "",
85
- tenantHint: "",
86
- theme: "light",
87
- ...options
88
- };
89
- }
90
- async login() {
91
- if (this.loginInProgress) {
92
- this.debug("login() ya en curso, ignorando llamada duplicada");
93
- return Promise.reject(new Error("Login already in progress"));
94
- }
95
- this.loginInProgress = true;
96
- this.authCompleted = false;
97
- const state = generateRandomId();
98
- const nonce = generateRandomId();
99
- const verifier = generateVerifier();
100
- const requestId = this.requestId;
101
- sessionStorage.setItem("sso_ctx", JSON.stringify({ state, nonce, verifier, requestId }));
102
- this.createUI();
103
- return new Promise((resolve, reject) => {
104
- this.abortController = new AbortController();
105
- const { signal } = this.abortController;
106
- const cleanup = () => {
107
- if (this.timeoutId) clearTimeout(this.timeoutId);
108
- if (this.messageListener) window.removeEventListener("message", this.messageListener);
109
- this.iframe?.remove();
110
- this.iframe = void 0;
111
- this.authCompleted = true;
112
- this.loginInProgress = false;
113
- };
114
- this.messageListener = async (event) => {
115
- if (event.origin !== this.options.ssoOrigin) {
116
- this.debug("Ignorado mensaje de origen no autorizado:", event.origin);
117
- return;
118
- }
119
- const msg = event.data;
120
- this.debug("Mensaje recibido:", msg);
121
- if (msg.requestId && msg.requestId !== requestId) {
122
- this.debug("requestId no coincide, ignorado");
123
- return;
124
- }
125
- if (msg.type === "sso-ready") {
126
- this.debug("sso-ready recibido, iniciando timeout y enviando sso-init");
127
- this.timeoutId = window.setTimeout(() => {
128
- if (!this.authCompleted) {
129
- this.debug("Timeout alcanzado, activando fallback");
130
- this.closeUI();
131
- cleanup();
132
- this.emit("fallback");
133
- window.location.href = this.buildFallbackUrl();
134
- reject(new Error("Timeout"));
135
- }
136
- }, this.options.timeout);
137
- const codeChallenge = await sha256Base64Url(verifier);
138
- const initPayload = {
139
- state,
140
- nonce,
141
- code_challenge: codeChallenge,
142
- code_challenge_method: "S256",
143
- origin: window.location.origin,
144
- ...this.options.redirectUri && { redirect_uri: this.options.redirectUri },
145
- ...this.options.tenantHint && { tenant_hint: this.options.tenantHint },
146
- timeout_ms: this.options.timeout
147
- };
148
- this.iframe?.contentWindow?.postMessage({
149
- v: "2.3",
150
- source: "@app/widget",
151
- type: "sso-init",
152
- requestId: this.requestId,
153
- payload: initPayload
154
- }, this.options.ssoOrigin);
155
- this.emit("ready");
156
- return;
157
- }
158
- if (msg.type === "sso-success") {
159
- this.debug("sso-success recibido");
160
- clearTimeout(this.timeoutId);
161
- try {
162
- const payload = msg.payload;
163
- const ctx = JSON.parse(sessionStorage.getItem("sso_ctx") || "{}");
164
- if (payload.state !== ctx.state) {
165
- throw new Error("Invalid state");
166
- }
167
- const decoded = await verifySignedPayload(
168
- payload.signed_payload,
169
- this.options.jwksUrl,
170
- window.location.origin
171
- );
172
- if (decoded.nonce !== ctx.nonce) {
173
- throw new Error("Invalid nonce");
174
- }
175
- this.debug("JWS v\xE1lido, payload:", decoded);
176
- this.closeUI();
177
- cleanup();
178
- const result = {
179
- code: decoded.code,
180
- state: decoded.state || ctx.state,
181
- nonce: ctx.nonce,
182
- codeVerifier: ctx.verifier,
183
- signed_payload: payload.signed_payload,
184
- tenant: decoded.tenant,
185
- jti: decoded.jti,
186
- iss: decoded.iss,
187
- aud: typeof decoded.aud === "string" ? decoded.aud : void 0,
188
- exp: decoded.exp,
189
- iat: decoded.iat
190
- };
191
- this.emit("success", result);
192
- resolve(result);
193
- } catch (err) {
194
- this.debug("Error en sso-success:", err);
195
- this.closeUI();
196
- cleanup();
197
- this.emit("error", err);
198
- reject(err);
199
- }
200
- return;
201
- }
202
- if (msg.type === "sso-error") {
203
- const errorPayload = msg.payload;
204
- this.debug("sso-error recibido:", errorPayload);
205
- clearTimeout(this.timeoutId);
206
- this.closeUI();
207
- cleanup();
208
- if (errorPayload.code === "version_mismatch") {
209
- this.emit("error", errorPayload);
210
- window.location.href = this.buildFallbackUrl();
211
- reject(new Error(`Version mismatch: expected ${errorPayload.expected_version}`));
212
- } else {
213
- this.emit("error", errorPayload);
214
- reject(errorPayload);
215
- }
216
- }
217
- if (msg.type === "sso-close") {
218
- this.debug("sso-close recibido");
219
- this.closeUI();
220
- cleanup();
221
- reject(new Error("Login cancelled by user"));
222
- }
223
- };
224
- window.addEventListener("message", this.messageListener);
225
- signal.addEventListener("abort", () => {
226
- this.debug("Operaci\xF3n abortada");
227
- this.closeUI();
228
- cleanup();
229
- reject(new Error("Login aborted"));
230
- });
231
- });
232
- }
233
- abort() {
234
- this.abortController?.abort();
235
- }
236
- // ─── UI Management ───────────────────────────────────────────────
237
- createUI() {
238
- if (!this.hostEl) {
239
- this.hostEl = document.createElement("div");
240
- this.hostEl.id = "bigso-auth-host";
241
- this.shadowRoot = this.hostEl.attachShadow({ mode: "open" });
242
- const style = document.createElement("style");
243
- style.textContent = this.getOverlayStyles();
244
- this.shadowRoot.appendChild(style);
245
- this.overlayEl = document.createElement("div");
246
- this.overlayEl.className = "sso-overlay";
247
- const closeBtn = document.createElement("button");
248
- closeBtn.className = "sso-close-btn";
249
- closeBtn.innerHTML = "×";
250
- closeBtn.setAttribute("aria-label", "Cerrar modal");
251
- closeBtn.addEventListener("click", () => this.abort());
252
- this.overlayEl.appendChild(closeBtn);
253
- this.overlayEl.addEventListener("click", (event) => {
254
- if (event.target === this.overlayEl) {
255
- this.abort();
256
- }
257
- });
258
- this.shadowRoot.appendChild(this.overlayEl);
259
- document.body.appendChild(this.hostEl);
260
- }
261
- this.iframe = document.createElement("iframe");
262
- this.iframe.className = "sso-frame";
263
- this.iframe.src = `${this.options.ssoOrigin}/auth/sign-in?v=2.3&client_id=${this.options.clientId}`;
264
- this.iframe.setAttribute("title", "SSO Login");
265
- this.overlayEl.appendChild(this.iframe);
266
- this.debug("Iframe creado", this.iframe.src);
267
- this.overlayEl.classList.remove("sso-closing");
268
- this.overlayEl.style.display = "flex";
269
- }
270
- closeUI() {
271
- if (!this.overlayEl || this.overlayEl.style.display === "none") return;
272
- this.overlayEl.classList.add("sso-closing");
273
- setTimeout(() => {
274
- if (this.overlayEl) {
275
- this.overlayEl.style.display = "none";
276
- this.overlayEl.classList.remove("sso-closing");
277
- }
278
- }, 200);
279
- }
280
- getOverlayStyles() {
281
- return `
282
- .sso-overlay {
283
- position: fixed;
284
- inset: 0;
285
- display: none;
286
- justify-content: center;
287
- align-items: center;
288
- background: rgba(0, 0, 0, 0.6);
289
- z-index: 999999;
290
- backdrop-filter: blur(4px);
291
- -webkit-backdrop-filter: blur(4px);
292
- animation: fadeIn 0.2s ease;
293
- }
294
- .sso-frame {
295
- width: 370px;
296
- height: 350px;
297
- border: none;
298
- border-radius: 16px;
299
- background: var(--card-bg, #fff);
300
- box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
301
- animation: slideUp 0.3s ease;
302
- }
303
- @media (max-width: 480px), (max-height: 480px) {
304
- .sso-frame {
305
- width: 100%;
306
- height: 100%;
307
- border-radius: 0;
308
- }
309
- }
310
- .sso-close-btn {
311
- position: absolute;
312
- top: 12px;
313
- right: 12px;
314
- width: 32px;
315
- height: 32px;
316
- background: rgba(0, 0, 0, 0.4);
317
- color: white;
318
- border: none;
319
- border-radius: 50%;
320
- font-size: 24px;
321
- line-height: 1;
322
- cursor: pointer;
323
- display: flex;
324
- align-items: center;
325
- justify-content: center;
326
- z-index: 1000000;
327
- transition: background 0.2s;
328
- }
329
- .sso-close-btn:hover {
330
- background: rgba(0, 0, 0, 0.8);
331
- }
332
- .sso-overlay.sso-closing {
333
- animation: fadeOut 0.2s ease forwards;
334
- }
335
- .sso-overlay.sso-closing .sso-frame {
336
- animation: slideDown 0.2s ease forwards;
337
- }
338
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
339
- @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
340
- @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
341
- @keyframes slideDown { from { transform: translateY(0); opacity: 1; } to { transform: translateY(20px); opacity: 0; } }
342
- `;
343
- }
344
- // ─── Helpers ──────────────────────────────────────────────────────
345
- buildFallbackUrl() {
346
- const url = new URL(this.options.ssoOrigin);
347
- url.searchParams.set("app_id", this.options.clientId);
348
- url.searchParams.set("redirect_uri", this.options.redirectUri || window.location.origin);
349
- url.searchParams.set("response_type", "code");
350
- url.searchParams.set("state", generateRandomId());
351
- url.searchParams.set("code_challenge_method", "S256");
352
- url.searchParams.set("client_id", this.options.clientId);
353
- return url.toString();
354
- }
355
- debug(...args) {
356
- if (this.options.debug) {
357
- console.log("[BigsoAuth]", ...args);
358
- }
359
- }
360
- };
361
- // Annotate the CommonJS export names for ESM import in node:
362
- 0 && (module.exports = {
363
- BigsoAuth
364
- });
@@ -1,32 +0,0 @@
1
- import { B as BigsoAuthOptions, a as BigsoAuthResult } from '../types-BQzACpj3.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
- login(): Promise<BigsoAuthResult>;
24
- abort(): void;
25
- private createUI;
26
- private closeUI;
27
- private getOverlayStyles;
28
- private buildFallbackUrl;
29
- private debug;
30
- }
31
-
32
- export { BigsoAuth, BigsoAuthOptions, BigsoAuthResult };
@@ -1,32 +0,0 @@
1
- import { B as BigsoAuthOptions, a as BigsoAuthResult } from '../types-BQzACpj3.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
- login(): Promise<BigsoAuthResult>;
24
- abort(): void;
25
- private createUI;
26
- private closeUI;
27
- private getOverlayStyles;
28
- private buildFallbackUrl;
29
- private debug;
30
- }
31
-
32
- export { BigsoAuth, BigsoAuthOptions, BigsoAuthResult };