@nibssplc/cams-sdk-react 1.0.0-rc.6 → 1.0.0-rc.61

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.
@@ -0,0 +1,908 @@
1
+ import { useState, useRef, useEffect, useCallback, createContext, useContext, useMemo } from 'react';
2
+ import { CAMSSessionManager, isPopupWindow, CAMSMFAAuthenticator, Logger, CAMSError, CAMSErrorType } from '@nibssplc/cams-sdk';
3
+ export * from '@nibssplc/cams-sdk';
4
+ import { useMsal, useAccount, MsalProvider } from '@azure/msal-react';
5
+ import { InteractionStatus, PublicClientApplication } from '@azure/msal-browser';
6
+ import { jsx, Fragment } from 'react/jsx-runtime';
7
+ import { z } from 'zod';
8
+
9
+ /******************************************************************************
10
+ Copyright (c) Microsoft Corporation.
11
+
12
+ Permission to use, copy, modify, and/or distribute this software for any
13
+ purpose with or without fee is hereby granted.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
16
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
18
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21
+ PERFORMANCE OF THIS SOFTWARE.
22
+ ***************************************************************************** */
23
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
24
+
25
+
26
+ var __assign = function() {
27
+ __assign = Object.assign || function __assign(t) {
28
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
29
+ s = arguments[i];
30
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
31
+ }
32
+ return t;
33
+ };
34
+ return __assign.apply(this, arguments);
35
+ };
36
+
37
+ function __rest(s, e) {
38
+ var t = {};
39
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
40
+ t[p] = s[p];
41
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
42
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
43
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
44
+ t[p[i]] = s[p[i]];
45
+ }
46
+ return t;
47
+ }
48
+
49
+ function __awaiter$1(thisArg, _arguments, P, generator) {
50
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
51
+ return new (P || (P = Promise))(function (resolve, reject) {
52
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
53
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
54
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
55
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
56
+ });
57
+ }
58
+
59
+ function __generator$1(thisArg, body) {
60
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
61
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
62
+ function verb(n) { return function (v) { return step([n, v]); }; }
63
+ function step(op) {
64
+ if (f) throw new TypeError("Generator is already executing.");
65
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
66
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
67
+ if (y = 0, t) op = [op[0] & 2, t.value];
68
+ switch (op[0]) {
69
+ case 0: case 1: t = op; break;
70
+ case 4: _.label++; return { value: op[1], done: false };
71
+ case 5: _.label++; y = op[1]; op = [0]; continue;
72
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
73
+ default:
74
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
75
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
76
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
77
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
78
+ if (t[2]) _.ops.pop();
79
+ _.trys.pop(); continue;
80
+ }
81
+ op = body.call(thisArg, _);
82
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
83
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
84
+ }
85
+ }
86
+
87
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
88
+ var e = new Error(message);
89
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
90
+ };
91
+
92
+ function useCAMSAuth(options) {
93
+ var _this = this;
94
+ var _a;
95
+ if (options === void 0) { options = {
96
+ appCode: "",
97
+ loginExpiry: 1,
98
+ storageKey: "CAMS-AUTH-SDK",
99
+ }; }
100
+ var _b = useState(false), isAuthenticated = _b[0], setIsAuthenticated = _b[1];
101
+ var _c = useState(false), isLoading = _c[0], setIsLoading = _c[1];
102
+ var _d = useState(null), error = _d[0], setError = _d[1];
103
+ var _e = useState(""), token = _e[0], setToken = _e[1];
104
+ var _f = useState(null), profile = _f[0], setProfile = _f[1];
105
+ var sessionManagerRef = useRef(null);
106
+ useEffect(function () {
107
+ var _a, _b;
108
+ // Only initialize on client side
109
+ if (typeof window === "undefined")
110
+ return;
111
+ (_a = sessionManagerRef.current) !== null && _a !== void 0 ? _a : (sessionManagerRef.current = new CAMSSessionManager(localStorage, options.storageKey || "CAMS-AUTH-SDK", {
112
+ onAuthSuccess: function (res) {
113
+ var _a;
114
+ setToken(res.userProfile.tokens.Bearer);
115
+ setIsAuthenticated(true);
116
+ setIsLoading(false);
117
+ (_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, res.userProfile.tokens.Bearer);
118
+ },
119
+ onAuthError: function (error) {
120
+ var _a;
121
+ setError(error);
122
+ setIsAuthenticated(false);
123
+ setToken("");
124
+ setProfile(null);
125
+ setIsLoading(false);
126
+ (_a = options.onAuthError) === null || _a === void 0 ? void 0 : _a.call(options, error);
127
+ },
128
+ onTokenExpired: function () {
129
+ var _a;
130
+ setIsAuthenticated(false);
131
+ setToken("");
132
+ setProfile(null);
133
+ (_a = options.onTokenExpired) === null || _a === void 0 ? void 0 : _a.call(options);
134
+ },
135
+ }));
136
+ // Check initial auth state (skip if in popup)
137
+ if (!isPopupWindow()) {
138
+ var initialAuth = sessionManagerRef.current.isAuthenticated();
139
+ setIsAuthenticated(initialAuth);
140
+ if (initialAuth) {
141
+ setToken((_b = sessionManagerRef.current.getAccessToken()) !== null && _b !== void 0 ? _b : "");
142
+ sessionManagerRef.current.getProfile().then(setProfile);
143
+ }
144
+ }
145
+ }, [options.storageKey]);
146
+ var login = useCallback(function (config) { return __awaiter$1(_this, void 0, void 0, function () {
147
+ var loginConfig, userProfile, err_1, e, isPopupClosedError, restoredToken, userProfile;
148
+ var _a, _b, _c;
149
+ return __generator$1(this, function (_d) {
150
+ switch (_d.label) {
151
+ case 0:
152
+ if (!sessionManagerRef.current)
153
+ return [2 /*return*/];
154
+ setIsLoading(true);
155
+ setError(null);
156
+ _d.label = 1;
157
+ case 1:
158
+ _d.trys.push([1, 4, 8, 9]);
159
+ loginConfig = __assign(__assign({}, config), { idleTimeout: options.idleTimeout });
160
+ return [4 /*yield*/, sessionManagerRef.current.login(loginConfig)];
161
+ case 2:
162
+ _d.sent();
163
+ return [4 /*yield*/, sessionManagerRef.current.getProfile()];
164
+ case 3:
165
+ userProfile = _d.sent();
166
+ setProfile(userProfile);
167
+ return [3 /*break*/, 9];
168
+ case 4:
169
+ err_1 = _d.sent();
170
+ e = err_1;
171
+ isPopupClosedError = ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes("Authentication window was closed")) ||
172
+ (e === null || e === void 0 ? void 0 : e.error) === "Authentication window was closed";
173
+ if (!(isPopupClosedError && sessionManagerRef.current.isAuthenticated())) return [3 /*break*/, 6];
174
+ restoredToken = (_b = sessionManagerRef.current.getAccessToken()) !== null && _b !== void 0 ? _b : "";
175
+ setToken(restoredToken);
176
+ setIsAuthenticated(true);
177
+ return [4 /*yield*/, sessionManagerRef.current.getProfile()];
178
+ case 5:
179
+ userProfile = _d.sent();
180
+ setProfile(userProfile);
181
+ (_c = options.onAuthSuccess) === null || _c === void 0 ? void 0 : _c.call(options, restoredToken);
182
+ return [3 /*break*/, 7];
183
+ case 6:
184
+ setError(err_1);
185
+ setIsAuthenticated(false);
186
+ setToken("");
187
+ setProfile(null);
188
+ _d.label = 7;
189
+ case 7: return [3 /*break*/, 9];
190
+ case 8:
191
+ setIsLoading(false);
192
+ return [7 /*endfinally*/];
193
+ case 9: return [2 /*return*/];
194
+ }
195
+ });
196
+ }); }, [options.idleTimeout]);
197
+ var logout = useCallback(function () { return __awaiter$1(_this, void 0, void 0, function () {
198
+ return __generator$1(this, function (_a) {
199
+ switch (_a.label) {
200
+ case 0:
201
+ if (!sessionManagerRef.current)
202
+ return [2 /*return*/];
203
+ return [4 /*yield*/, sessionManagerRef.current.logout()];
204
+ case 1:
205
+ _a.sent();
206
+ setIsAuthenticated(false);
207
+ setToken("");
208
+ setProfile(null);
209
+ setError(null);
210
+ return [2 /*return*/];
211
+ }
212
+ });
213
+ }); }, []);
214
+ return {
215
+ login: login,
216
+ logout: logout,
217
+ isAuthenticated: isAuthenticated,
218
+ isLoading: isLoading,
219
+ error: error,
220
+ token: token,
221
+ profile: profile,
222
+ loginExpiry: (_a = options.loginExpiry) !== null && _a !== void 0 ? _a : 1,
223
+ appCode: options.appCode,
224
+ storageKey: options.storageKey || "CAMS-AUTH-SDK",
225
+ };
226
+ }
227
+
228
+ var _a;
229
+ // Crypto polyfill for MSAL browser compatibility
230
+ // Only apply if crypto.subtle is completely missing
231
+ if (typeof window !== "undefined" && !((_a = window.crypto) === null || _a === void 0 ? void 0 : _a.subtle)) {
232
+ // Ensure crypto object exists
233
+ if (!window.crypto) {
234
+ window.crypto = {};
235
+ }
236
+ // Polyfill getRandomValues
237
+ if (!window.crypto.getRandomValues) {
238
+ window.crypto.getRandomValues = function (array) {
239
+ var bytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
240
+ for (var i = 0; i < bytes.length; i++) {
241
+ bytes[i] = Math.floor(Math.random() * 256);
242
+ }
243
+ return array;
244
+ };
245
+ }
246
+ var sha256_1 = function (data) { return __awaiter(void 0, void 0, void 0, function () {
247
+ var toUint8, bytes, hash, k, ml, msg, dv, high, low, i, w, j, j, s0, s1, a, b, c, d, e, f, g, h, j, S1, ch, temp1, S0, maj, temp2, result, i;
248
+ return __generator(this, function (_a) {
249
+ toUint8 = function (src) {
250
+ if (src instanceof ArrayBuffer)
251
+ return new Uint8Array(src);
252
+ if (ArrayBuffer.isView(src)) {
253
+ var view = src;
254
+ return new Uint8Array(view.buffer, view.byteOffset || 0, view.byteLength);
255
+ }
256
+ throw new TypeError("Unsupported BufferSource");
257
+ };
258
+ bytes = toUint8(data);
259
+ hash = new Uint32Array(8);
260
+ k = new Uint32Array([
261
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
262
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
263
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
264
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
265
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
266
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
267
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
268
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
269
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
270
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
271
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
272
+ ]);
273
+ hash[0] = 0x6a09e667;
274
+ hash[1] = 0xbb67ae85;
275
+ hash[2] = 0x3c6ef372;
276
+ hash[3] = 0xa54ff53a;
277
+ hash[4] = 0x510e527f;
278
+ hash[5] = 0x9b05688c;
279
+ hash[6] = 0x1f83d9ab;
280
+ hash[7] = 0x5be0cd19;
281
+ ml = bytes.length * 8;
282
+ msg = new Uint8Array(bytes.length + 64 + ((64 - ((bytes.length + 9) % 64)) % 64));
283
+ msg.set(bytes);
284
+ msg[bytes.length] = 0x80;
285
+ dv = new DataView(msg.buffer);
286
+ high = Math.floor(ml / 0x100000000);
287
+ low = ml >>> 0;
288
+ dv.setUint32(msg.length - 8, high, false);
289
+ dv.setUint32(msg.length - 4, low, false);
290
+ for (i = 0; i < msg.length; i += 64) {
291
+ w = new Uint32Array(64);
292
+ for (j = 0; j < 16; j++)
293
+ w[j] = new DataView(msg.buffer).getUint32(i + j * 4, false);
294
+ for (j = 16; j < 64; j++) {
295
+ s0 = ((w[j - 15] >>> 7) | (w[j - 15] << 25)) ^
296
+ ((w[j - 15] >>> 18) | (w[j - 15] << 14)) ^
297
+ (w[j - 15] >>> 3);
298
+ s1 = ((w[j - 2] >>> 17) | (w[j - 2] << 15)) ^
299
+ ((w[j - 2] >>> 19) | (w[j - 2] << 13)) ^
300
+ (w[j - 2] >>> 10);
301
+ w[j] = (w[j - 16] + s0 + w[j - 7] + s1) >>> 0;
302
+ }
303
+ a = hash[0], b = hash[1], c = hash[2], d = hash[3], e = hash[4], f = hash[5], g = hash[6], h = hash[7];
304
+ for (j = 0; j < 64; j++) {
305
+ S1 = ((e >>> 6) | (e << 26)) ^
306
+ ((e >>> 11) | (e << 21)) ^
307
+ ((e >>> 25) | (e << 7));
308
+ ch = (e & f) ^ (~e & g);
309
+ temp1 = (h + S1 + ch + k[j] + w[j]) >>> 0;
310
+ S0 = ((a >>> 2) | (a << 30)) ^
311
+ ((a >>> 13) | (a << 19)) ^
312
+ ((a >>> 22) | (a << 10));
313
+ maj = (a & b) ^ (a & c) ^ (b & c);
314
+ temp2 = (S0 + maj) >>> 0;
315
+ h = g;
316
+ g = f;
317
+ f = e;
318
+ e = (d + temp1) >>> 0;
319
+ d = c;
320
+ c = b;
321
+ b = a;
322
+ a = (temp1 + temp2) >>> 0;
323
+ }
324
+ hash[0] = (hash[0] + a) >>> 0;
325
+ hash[1] = (hash[1] + b) >>> 0;
326
+ hash[2] = (hash[2] + c) >>> 0;
327
+ hash[3] = (hash[3] + d) >>> 0;
328
+ hash[4] = (hash[4] + e) >>> 0;
329
+ hash[5] = (hash[5] + f) >>> 0;
330
+ hash[6] = (hash[6] + g) >>> 0;
331
+ hash[7] = (hash[7] + h) >>> 0;
332
+ }
333
+ result = new Uint8Array(32);
334
+ for (i = 0; i < 8; i++)
335
+ new DataView(result.buffer).setUint32(i * 4, hash[i], false);
336
+ return [2 /*return*/, result.buffer];
337
+ });
338
+ }); };
339
+ // Create the polyfilled subtle object
340
+ var polyfillSubtle = {
341
+ digest: function (algorithm, data) { return __awaiter(void 0, void 0, void 0, function () {
342
+ var alg;
343
+ return __generator(this, function (_a) {
344
+ alg = typeof algorithm === "string"
345
+ ? algorithm
346
+ : algorithm.name;
347
+ if (alg === "SHA-256")
348
+ return [2 /*return*/, sha256_1(data)];
349
+ throw new Error("Unsupported algorithm: ".concat(alg));
350
+ });
351
+ }); },
352
+ };
353
+ // Set the polyfilled subtle object
354
+ window.crypto.subtle = polyfillSubtle;
355
+ // Polyfill randomUUID
356
+ if (!window.crypto.randomUUID) {
357
+ window.crypto.randomUUID =
358
+ function () {
359
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
360
+ var r = (Math.random() * 16) | 0;
361
+ var v = c === "x" ? r : (r & 0x3) | 0x8;
362
+ return v.toString(16);
363
+ });
364
+ };
365
+ }
366
+ console.log("Crypto polyfill applied (native crypto.subtle not available)");
367
+ }
368
+
369
+ var setCookie = function (name, value, days) {
370
+ if (days === void 0) { days = 1; }
371
+ var expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
372
+ console.log("Auth Cookie Expires >>>", { name: name, value: value, expires: expires });
373
+ document.cookie = "".concat(name, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/; samesite=Lax");
374
+ };
375
+ var getCookie = function (name) {
376
+ var _a;
377
+ return ((_a = document.cookie
378
+ .split("; ")
379
+ .find(function (row) { return row.startsWith(name + "="); })) === null || _a === void 0 ? void 0 : _a.split("=")[1])
380
+ ? decodeURIComponent(document.cookie
381
+ .split("; ")
382
+ .find(function (row) { return row.startsWith(name + "="); })
383
+ .split("=")[1])
384
+ : null;
385
+ };
386
+ var deleteCookie = function (name) {
387
+ document.cookie = name + "=; Max-Age=-99999999; path=/";
388
+ };
389
+
390
+ function useCAMSMSALAuth(options) {
391
+ var _this = this;
392
+ var optStorageKey = options.storageKey, optScopes = options.scopes, prompt = options.prompt, appCode = options.appCode, MFAEndpoint = options.MFAEndpoint, _a = options.activeCookiePeriod, activeCookiePeriod = _a === void 0 ? 1 : _a;
393
+ var storageKey = optStorageKey || "CAMS-MSAL-AUTH-SDK";
394
+ var _b = useMsal(), instance = _b.instance, inProgress = _b.inProgress, accounts = _b.accounts;
395
+ var account = useAccount(accounts[0] || {});
396
+ var _c = useState(null), error = _c[0], setError = _c[1];
397
+ var _d = useState(""), idToken = _d[0], setIdToken = _d[1];
398
+ var _e = useState(""), accessToken = _e[0], setAccessToken = _e[1];
399
+ var _f = useState(null), mfaAuthenticator = _f[0], setMfaAuthenticator = _f[1];
400
+ var _g = useState(false), requiresMFA = _g[0], setRequiresMFA = _g[1];
401
+ var isLoading = inProgress !== InteractionStatus.None;
402
+ var isAuthenticated = !!account && !!accessToken && !requiresMFA;
403
+ var scopes = optScopes || ["openid", "profile", "email"];
404
+ var isTokenValid = function (token) {
405
+ try {
406
+ var payload = JSON.parse(atob(token.split(".")[1]));
407
+ return payload.exp * 1000 > Date.now();
408
+ }
409
+ catch (_a) {
410
+ return false;
411
+ }
412
+ };
413
+ useEffect(function () {
414
+ if (typeof window !== "undefined" && !accessToken) {
415
+ var stored = localStorage.getItem(storageKey);
416
+ if (stored) {
417
+ try {
418
+ var _a = JSON.parse(stored), accessToken_1 = _a.accessToken, idToken_1 = _a.idToken, storedRequiresMFA = _a.requiresMFA, storedIsAuthenticated = _a.isAuthenticated;
419
+ if (accessToken_1 && isTokenValid(accessToken_1)) {
420
+ setAccessToken(accessToken_1);
421
+ setIdToken(idToken_1);
422
+ // Restore MFA state
423
+ if (storedRequiresMFA && !storedIsAuthenticated) {
424
+ var mfaConfig = {
425
+ accessToken: accessToken_1,
426
+ idToken: idToken_1,
427
+ appCode: appCode,
428
+ provider: "MSAL",
429
+ apiEndpoint: MFAEndpoint,
430
+ };
431
+ var authenticator = new CAMSMFAAuthenticator(mfaConfig);
432
+ setMfaAuthenticator(authenticator);
433
+ setRequiresMFA(true);
434
+ }
435
+ }
436
+ else {
437
+ localStorage.removeItem(storageKey);
438
+ }
439
+ }
440
+ catch (_b) { }
441
+ }
442
+ else if (account) {
443
+ // Storage cleared but MSAL account exists - clear MSAL state
444
+ instance.logoutRedirect().catch(function () { });
445
+ }
446
+ }
447
+ }, [accessToken, account, instance, options.storageKey]);
448
+ // useEffect(() => {
449
+ // const handleRedirect = async () => {
450
+ // try {
451
+ // const response = await instance.handleRedirectPromise();
452
+ // if (response) {
453
+ // const account = response.account;
454
+ // instance.setActiveA ccount(account);
455
+ // const tokenResponse = await instance.acq uireTokenSilent({
456
+ // scopes,
457
+ // account,
458
+ // });
459
+ // setToken(tokenResponse.accessToken);
460
+ // setAccessToken(tokenResponse.accessToken);
461
+ // setIdToken(tokenResponse.idTo ken);
462
+ // options.onAuthSuccess?.(tokenR esponse.accessToken);
463
+ // if (
464
+ // typeof window !== "undefined" &&
465
+ // process.env.NODE_ENV !== "test"
466
+ // ) {
467
+ // window.location.href = options.mfaUrl!;
468
+ // }
469
+ // }
470
+ // } catch (err) {
471
+ // console.error("Redirect handling failed:", err);
472
+ // }
473
+ // };
474
+ // handleRedirect();
475
+ // }, []);
476
+ var login = useCallback(function () { return __awaiter$1(_this, void 0, void 0, function () {
477
+ var response, mfaConfig, authenticator, err_1, camsError_1, camsError;
478
+ var _a;
479
+ return __generator$1(this, function (_b) {
480
+ switch (_b.label) {
481
+ case 0:
482
+ if (inProgress !== InteractionStatus.None) {
483
+ Logger.warn("Authentication already in progress, ignoring duplicate call");
484
+ return [2 /*return*/];
485
+ }
486
+ setError(null);
487
+ _b.label = 1;
488
+ case 1:
489
+ _b.trys.push([1, 3, , 4]);
490
+ return [4 /*yield*/, instance.loginPopup({
491
+ scopes: scopes,
492
+ prompt: prompt || "login",
493
+ })];
494
+ case 2:
495
+ response = _b.sent();
496
+ console.log("Login Token response:", {
497
+ accessToken: response.accessToken,
498
+ idToken: response.idToken,
499
+ });
500
+ setAccessToken(response.accessToken);
501
+ setIdToken(response.idToken);
502
+ mfaConfig = {
503
+ accessToken: response.accessToken,
504
+ idToken: response.idToken,
505
+ appCode: appCode,
506
+ provider: "MSAL",
507
+ apiEndpoint: MFAEndpoint,
508
+ };
509
+ authenticator = new CAMSMFAAuthenticator(mfaConfig);
510
+ setMfaAuthenticator(authenticator);
511
+ setRequiresMFA(true);
512
+ // Don't persist as authenticated until MFA is complete
513
+ if (typeof window !== "undefined") {
514
+ localStorage.setItem(storageKey, JSON.stringify({
515
+ isAuthenticated: false,
516
+ requiresMFA: true,
517
+ accessToken: response.accessToken,
518
+ idToken: response.idToken,
519
+ }));
520
+ }
521
+ return [3 /*break*/, 4];
522
+ case 3:
523
+ err_1 = _b.sent();
524
+ // Handle interaction_in_progress error
525
+ if (err_1.errorCode === "interaction_in_progress") {
526
+ Logger.warn("Interaction already in progress, please wait");
527
+ return [2 /*return*/];
528
+ }
529
+ // Handle user cancellation gracefully
530
+ if (err_1.errorCode === "user_cancelled") {
531
+ Logger.error("User cancelled login");
532
+ setError(null); // Don't treat cancellation as an error
533
+ return [2 /*return*/];
534
+ }
535
+ // If popup is blocked
536
+ if (err_1.errorCode === "popup_window_error" ||
537
+ ((_a = err_1.message) === null || _a === void 0 ? void 0 : _a.includes("popup"))) {
538
+ camsError_1 = new CAMSError(CAMSErrorType.POPUP_BLOCKED, "Popup blocked by browser. Please allow popups and try again.");
539
+ setError(camsError_1);
540
+ return [2 /*return*/];
541
+ }
542
+ camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1.message || err_1);
543
+ setError(camsError);
544
+ return [3 /*break*/, 4];
545
+ case 4: return [2 /*return*/];
546
+ }
547
+ });
548
+ }); }, [
549
+ instance,
550
+ scopes,
551
+ prompt,
552
+ appCode,
553
+ MFAEndpoint,
554
+ storageKey,
555
+ inProgress,
556
+ ]);
557
+ var completeMFA = useCallback(function (data) { return __awaiter$1(_this, void 0, void 0, function () {
558
+ return __generator$1(this, function (_a) {
559
+ if (!mfaAuthenticator) {
560
+ throw new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "MFA Authenticator not initialized");
561
+ }
562
+ Logger.info("Completed MFA.. Setting State");
563
+ try {
564
+ // Update storage with complete authentication BEFORE setting state
565
+ if (typeof window !== "undefined") {
566
+ localStorage.setItem(storageKey, JSON.stringify({
567
+ isAuthenticated: true,
568
+ requiresMFA: false,
569
+ accessToken: accessToken,
570
+ idToken: idToken,
571
+ }));
572
+ setCookie("CAMS-MSAL-AUTH-SDK-PROFILE", JSON.stringify({ type: "AUTH_SUCCESS", userProfile: __assign({}, data) }), activeCookiePeriod);
573
+ setRequiresMFA(false);
574
+ // Set requiresMFA to false after storage update
575
+ Logger.debug("MFA completed successfully, storage updated", {
576
+ accessToken: accessToken,
577
+ idToken: idToken,
578
+ isAuthenticated: true,
579
+ requiresMFA: false,
580
+ });
581
+ }
582
+ Logger.debug("MFA completed successfully, requiresMFA set to false");
583
+ return [2 /*return*/, data];
584
+ }
585
+ catch (error) {
586
+ setError(error);
587
+ throw error;
588
+ }
589
+ return [2 /*return*/];
590
+ });
591
+ }); }, [mfaAuthenticator, accessToken, idToken, storageKey, activeCookiePeriod]);
592
+ var sendEmailOTP = useCallback(function () { return __awaiter$1(_this, void 0, void 0, function () {
593
+ return __generator$1(this, function (_a) {
594
+ switch (_a.label) {
595
+ case 0:
596
+ if (!mfaAuthenticator) {
597
+ return [2 /*return*/, false];
598
+ }
599
+ return [4 /*yield*/, mfaAuthenticator.sendEmailOTP()];
600
+ case 1: return [2 /*return*/, _a.sent()];
601
+ }
602
+ });
603
+ }); }, [mfaAuthenticator]);
604
+ var logout = useCallback(function () { return __awaiter$1(_this, void 0, void 0, function () {
605
+ var err_2, camsError;
606
+ return __generator$1(this, function (_a) {
607
+ switch (_a.label) {
608
+ case 0:
609
+ _a.trys.push([0, 2, , 3]);
610
+ Logger.info("Logging User Out");
611
+ return [4 /*yield*/, instance.logoutRedirect()];
612
+ case 1:
613
+ _a.sent();
614
+ setAccessToken("");
615
+ setIdToken("");
616
+ setError(null);
617
+ setMfaAuthenticator(null);
618
+ setRequiresMFA(false);
619
+ if (typeof window !== "undefined") {
620
+ localStorage.removeItem(storageKey);
621
+ // deleteCookie("CAMS-MSAL-AUTH-SDK-PROFILE");
622
+ }
623
+ return [3 /*break*/, 3];
624
+ case 2:
625
+ err_2 = _a.sent();
626
+ camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Logout failed: " + err_2);
627
+ setError(camsError);
628
+ return [3 /*break*/, 3];
629
+ case 3: return [2 /*return*/];
630
+ }
631
+ });
632
+ }); }, [instance, storageKey]);
633
+ return {
634
+ login: login,
635
+ logout: logout,
636
+ storageKey: storageKey,
637
+ isAuthenticated: isAuthenticated,
638
+ isLoading: isLoading,
639
+ error: error,
640
+ idToken: idToken,
641
+ accessToken: accessToken,
642
+ appCode: appCode,
643
+ mfaAuthenticator: mfaAuthenticator,
644
+ requiresMFA: requiresMFA,
645
+ completeMFA: completeMFA,
646
+ sendEmailOTP: sendEmailOTP,
647
+ setRequiresMFA: setRequiresMFA,
648
+ activeCookiePeriod: activeCookiePeriod,
649
+ };
650
+ }
651
+
652
+ var CAMSContext$1 = createContext(null);
653
+ function useCAMSContext$1() {
654
+ var context = useContext(CAMSContext$1);
655
+ if (!context) {
656
+ throw new Error('useCAMSContext must be used within a CAMSProvider');
657
+ }
658
+ return context;
659
+ }
660
+
661
+ function ProtectedRoute(_a) {
662
+ var children = _a.children, fallback = _a.fallback, redirectTo = _a.redirectTo;
663
+ var _b = useCAMSContext$1(), isAuthenticated = _b.isAuthenticated, isLoading = _b.isLoading;
664
+ if (isLoading) {
665
+ return fallback || jsx("div", { className: 'h-screen flex items-center justify-center', children: "Loading..." });
666
+ }
667
+ if (!isAuthenticated) {
668
+ if (redirectTo && typeof window !== 'undefined') {
669
+ window.location.href = redirectTo;
670
+ return null;
671
+ }
672
+ return fallback || jsx("div", { children: "Access denied. Please log in." });
673
+ }
674
+ return jsx(Fragment, { children: children });
675
+ }
676
+
677
+ var CAMSMSALContext = createContext(null);
678
+ var isTokenValid = function (token) {
679
+ try {
680
+ var payload = JSON.parse(atob(token.split(".")[1]));
681
+ return payload.exp * 1000 > Date.now();
682
+ }
683
+ catch (_a) {
684
+ return false;
685
+ }
686
+ };
687
+ function CAMSMSALProviderInner(_a) {
688
+ var _this = this;
689
+ var children = _a.children, authOptions = __rest(_a, ["children"]);
690
+ var auth = useCAMSMSALAuth(authOptions);
691
+ var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
692
+ var getInitialProfile = function () {
693
+ if (typeof window === "undefined") {
694
+ return null;
695
+ }
696
+ try {
697
+ var storedProfile = getCookie(profileStorageKey);
698
+ return storedProfile ? JSON.parse(storedProfile) : null;
699
+ }
700
+ catch (_a) {
701
+ return null;
702
+ }
703
+ };
704
+ var _b = useState(getInitialProfile), userProfile = _b[0], setUserProfile = _b[1];
705
+ // Load profile from storage on mount
706
+ useEffect(function () {
707
+ if (typeof window !== "undefined") {
708
+ // const storedProfile = localStorage.get Item(profileStorageKey);
709
+ var storedProfile = getCookie(profileStorageKey);
710
+ if (storedProfile) {
711
+ try {
712
+ setUserProfile(JSON.parse(storedProfile));
713
+ }
714
+ catch (_a) { }
715
+ }
716
+ }
717
+ }, [profileStorageKey]);
718
+ // Persist tokens and profile
719
+ useEffect(function () {
720
+ if (auth.accessToken &&
721
+ isTokenValid(auth.accessToken) &&
722
+ typeof window !== "undefined") {
723
+ localStorage.setItem(auth.storageKey, JSON.stringify({
724
+ accessToken: auth.accessToken,
725
+ idToken: auth.idToken,
726
+ appCode: auth.appCode,
727
+ }));
728
+ }
729
+ }, [auth.accessToken, auth.idToken, auth.storageKey]);
730
+ // Persist profile separately
731
+ useEffect(function () {
732
+ if (typeof window !== "undefined") {
733
+ if (userProfile) {
734
+ setCookie(profileStorageKey, JSON.stringify(userProfile), 1); // Store for 1 day
735
+ }
736
+ else {
737
+ deleteCookie(profileStorageKey);
738
+ }
739
+ }
740
+ }, [userProfile, profileStorageKey]);
741
+ // Enhanced logout that also clears profile
742
+ var enhancedLogout = function () { return __awaiter$1(_this, void 0, void 0, function () {
743
+ return __generator$1(this, function (_a) {
744
+ switch (_a.label) {
745
+ case 0: return [4 /*yield*/, auth.logout()];
746
+ case 1:
747
+ _a.sent();
748
+ setUserProfile(null);
749
+ if (typeof window !== "undefined") {
750
+ deleteCookie(profileStorageKey);
751
+ }
752
+ return [2 /*return*/];
753
+ }
754
+ });
755
+ }); };
756
+ var value = useMemo(function () { return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile })); }, [auth, userProfile]);
757
+ return (jsx(CAMSMSALContext.Provider, { value: value, children: children }));
758
+ }
759
+ function CAMSMSALProvider(props) {
760
+ var _a;
761
+ var msalConfig = props.msalConfig, msalInstance = props.msalInstance;
762
+ // Ensure crypto is available before creating MSAL instance
763
+ if (typeof window !== "undefined" && !((_a = window.crypto) === null || _a === void 0 ? void 0 : _a.subtle)) {
764
+ throw new Error("Crypto API not available. Polyfill failed to load.");
765
+ }
766
+ var instance = msalInstance || new PublicClientApplication(msalConfig);
767
+ return (jsx(MsalProvider, { instance: instance, children: jsx(CAMSMSALProviderInner, __assign({}, props)) }));
768
+ }
769
+ function useCAMSMSALContext() {
770
+ var context = useContext(CAMSMSALContext);
771
+ if (!context) {
772
+ throw new Error("useCAMSMSALContext must be used within a CAMSMSALProvider");
773
+ }
774
+ return context;
775
+ }
776
+
777
+ var ClientOnly = function (_a) {
778
+ var children = _a.children, _b = _a.fallback, fallback = _b === void 0 ? null : _b;
779
+ var _c = useState(false), hasMounted = _c[0], setHasMounted = _c[1];
780
+ useEffect(function () {
781
+ setHasMounted(true);
782
+ }, []);
783
+ if (!hasMounted) {
784
+ return jsx(Fragment, { children: fallback });
785
+ }
786
+ return jsx(Fragment, { children: children });
787
+ };
788
+
789
+ var CAMSContext = createContext(null);
790
+ function useCAMSContext() {
791
+ var context = useContext(CAMSContext);
792
+ if (!context) {
793
+ throw new Error("useCAMSContext must be used within a UnifiedCAMSProvider");
794
+ }
795
+ return context;
796
+ }
797
+
798
+ var GuidSchema = z.uuid("appCode must be a valid GUID");
799
+ function CAMSProviderCore(props) {
800
+ var _this = this;
801
+ var children = props.children, mode = props.mode, appCode = props.appCode;
802
+ // Always call both hooks to satisfy Rules of Hooks
803
+ var regularAuth = useCAMSAuth(mode === "REGULAR"
804
+ ? __assign(__assign({}, props), { appCode: appCode })
805
+ : { appCode: "" });
806
+ var msalAuth = useCAMSMSALAuth(mode === "MSAL"
807
+ ? __assign(__assign({}, props), { appCode: appCode })
808
+ : { appCode: "" });
809
+ var auth = mode === "REGULAR" ? regularAuth : msalAuth;
810
+ var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
811
+ var getInitialProfile = function () {
812
+ if (typeof window === "undefined")
813
+ return null;
814
+ try {
815
+ var storedProfile = getCookie(profileStorageKey);
816
+ return storedProfile ? JSON.parse(storedProfile) : null;
817
+ }
818
+ catch (_a) {
819
+ return null;
820
+ }
821
+ };
822
+ var _a = useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
823
+ useEffect(function () {
824
+ if (typeof window !== "undefined") {
825
+ var storedProfile = getCookie(profileStorageKey);
826
+ if (storedProfile) {
827
+ try {
828
+ setUserProfile(JSON.parse(storedProfile));
829
+ }
830
+ catch (_a) { }
831
+ }
832
+ }
833
+ }, [profileStorageKey]);
834
+ useEffect(function () {
835
+ if (typeof window !== "undefined") {
836
+ if (userProfile) {
837
+ setCookie(profileStorageKey, JSON.stringify(userProfile), 1);
838
+ }
839
+ else {
840
+ deleteCookie(profileStorageKey);
841
+ }
842
+ }
843
+ }, [userProfile, profileStorageKey]);
844
+ var enhancedLogout = function () { return __awaiter$1(_this, void 0, void 0, function () {
845
+ return __generator$1(this, function (_a) {
846
+ switch (_a.label) {
847
+ case 0: return [4 /*yield*/, auth.logout()];
848
+ case 1:
849
+ _a.sent();
850
+ setUserProfile(null);
851
+ if (typeof window !== "undefined") {
852
+ deleteCookie(profileStorageKey);
853
+ }
854
+ return [2 /*return*/];
855
+ }
856
+ });
857
+ }); };
858
+ useEffect(function () {
859
+ if (mode === "MSAL" &&
860
+ "requiresMFA" in auth &&
861
+ !auth.requiresMFA &&
862
+ auth.isAuthenticated) {
863
+ var storedData = localStorage.getItem(auth.storageKey);
864
+ if (storedData) {
865
+ try {
866
+ var parsed = JSON.parse(storedData);
867
+ if (parsed.userProfile) {
868
+ setUserProfile(parsed.userProfile);
869
+ }
870
+ }
871
+ catch (_a) { }
872
+ }
873
+ }
874
+ }, [
875
+ mode,
876
+ "requiresMFA" in auth ? auth.requiresMFA : false,
877
+ auth.isAuthenticated,
878
+ auth.storageKey,
879
+ userProfile,
880
+ ]);
881
+ var value = useMemo(function () {
882
+ auth.logout; var authRest = __rest(auth, ["logout"]);
883
+ return __assign(__assign({}, authRest), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode, onAuthSuccess: mode === "MSAL" ? props.onAuthSuccess : undefined, onAuthError: mode === "MSAL" ? props.onAuthError : undefined });
884
+ }, [auth, userProfile, mode, props]);
885
+ return jsx(CAMSContext.Provider, { value: value, children: children });
886
+ }
887
+ function UnifiedCAMSProvider(props) {
888
+ var _a;
889
+ // Validate appCode is a valid GUID
890
+ var appCodeValidation = GuidSchema.safeParse(props.appCode);
891
+ if (!appCodeValidation.success) {
892
+ throw new Error("Invalid CAS APP CODE: ".concat(appCodeValidation.error.issues[0].message));
893
+ }
894
+ if (props.mode === "MSAL") {
895
+ var msalConfig = props.msalConfig, msalInstance = props.msalInstance;
896
+ if (typeof window !== "undefined" && !((_a = window.crypto) === null || _a === void 0 ? void 0 : _a.subtle)) {
897
+ throw new Error("Crypto API not available. Polyfill failed to load.");
898
+ }
899
+ var instance = msalInstance || new PublicClientApplication(msalConfig);
900
+ return (jsx(MsalProvider, { instance: instance, children: jsx(CAMSProviderCore, __assign({}, props)) }));
901
+ }
902
+ return (jsx(ClientOnly, { fallback: jsx("div", { className: 'h-screen flex items-center justify-center', children: "Loading..." }), children: jsx(CAMSProviderCore, __assign({}, props)) }));
903
+ }
904
+ // Backward compatibility exports
905
+ var CAMSProvider = function (props) { return (jsx(UnifiedCAMSProvider, __assign({}, props, { mode: "REGULAR" }))); };
906
+
907
+ export { CAMSMSALProvider, CAMSProvider, ClientOnly, ProtectedRoute, UnifiedCAMSProvider, useCAMSAuth, useCAMSContext, useCAMSMSALAuth, useCAMSMSALContext };
908
+ //# sourceMappingURL=index.server.js.map