@nibssplc/cams-sdk-react 0.0.1-beta.76 → 0.0.1-beta.77

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.esm.js CHANGED
@@ -2,8 +2,8 @@ import * as React from 'react';
2
2
  import React__default, { useState, useRef, useEffect, useCallback, createContext, useContext, useMemo } from 'react';
3
3
  import { isPopupWindow, initializePopupAuth, CAMSSessionManager, CAMSMFAAuthenticator, Logger, CAMSError, CAMSErrorType } from '@nibssplc/cams-sdk';
4
4
  export * from '@nibssplc/cams-sdk';
5
- import { useMsal, useAccount, MsalProvider } from '@azure/msal-react';
6
- import { InteractionStatus, PublicClientApplication } from '@azure/msal-browser';
5
+ import { MsalProvider, useMsal, useAccount } from '@azure/msal-react';
6
+ import { PublicClientApplication, InteractionStatus } from '@azure/msal-browser';
7
7
  import z$1, { z } from 'zod';
8
8
  import { OTPInput, OTPInputContext, REGEXP_ONLY_DIGITS } from 'input-otp';
9
9
  import { RectangleEllipsis, XIcon, CheckCircle, Mail, Shield, ShieldCheck, ShieldClose } from 'lucide-react';
@@ -236,315 +236,9 @@ function useCAMSAuth(options) {
236
236
  };
237
237
  }
238
238
 
239
- var CAMSContext$1 = createContext(null);
240
- function useCAMSContext$1() {
241
- var context = useContext(CAMSContext$1);
242
- if (!context) {
243
- throw new Error("useCAMSContext must be used within a UnifiedCAMSProvider");
244
- }
245
- return context;
246
- }
239
+ var jsxRuntime = {exports: {}};
247
240
 
248
- function useCAMSMSALAuth(options) {
249
- var _this = this;
250
- var storageKey = options.storageKey || "CAMS-MSAL-AUTH-SDK";
251
- var _a = useMsal(), instance = _a.instance, inProgress = _a.inProgress, accounts = _a.accounts;
252
- var account = useAccount(accounts[0] || {});
253
- var setUserProfile = useCAMSContext$1().setUserProfile;
254
- var _b = useState(null), error = _b[0], setError = _b[1];
255
- var _c = useState(""), idToken = _c[0], setIdToken = _c[1];
256
- var _d = useState(""), accessToken = _d[0], setAccessToken = _d[1];
257
- var _e = useState(null), mfaAuthenticator = _e[0], setMfaAuthenticator = _e[1];
258
- var _f = useState(false), requiresMFA = _f[0], setRequiresMFA = _f[1];
259
- var isLoading = inProgress !== InteractionStatus.None;
260
- var isAuthenticated = !!account && !!accessToken && !requiresMFA;
261
- var scopes = options.scopes || ["openid", "profile", "email"];
262
- var isTokenValid = function (token) {
263
- try {
264
- var payload = JSON.parse(atob(token.split(".")[1]));
265
- return payload.exp * 1000 > Date.now();
266
- }
267
- catch (_a) {
268
- return false;
269
- }
270
- };
271
- useEffect(function () {
272
- if (typeof window !== "undefined" && !accessToken) {
273
- var stored = localStorage.getItem(storageKey);
274
- if (stored) {
275
- try {
276
- var _a = JSON.parse(stored), accessToken_1 = _a.accessToken, idToken_1 = _a.idToken, storedRequiresMFA = _a.requiresMFA, storedIsAuthenticated = _a.isAuthenticated;
277
- if (accessToken_1 && isTokenValid(accessToken_1)) {
278
- setAccessToken(accessToken_1);
279
- setIdToken(idToken_1);
280
- // Restore MFA state
281
- if (storedRequiresMFA && !storedIsAuthenticated) {
282
- var mfaConfig = {
283
- accessToken: accessToken_1,
284
- idToken: idToken_1,
285
- appCode: options.appCode,
286
- provider: "MSAL",
287
- apiEndpoint: options.MFAEndpoint,
288
- };
289
- var authenticator = new CAMSMFAAuthenticator(mfaConfig);
290
- setMfaAuthenticator(authenticator);
291
- setRequiresMFA(true);
292
- }
293
- Logger.debug("App Code", { ">>>": options.appCode });
294
- }
295
- else {
296
- localStorage.removeItem(storageKey);
297
- }
298
- }
299
- catch (_b) { }
300
- }
301
- else if (account) {
302
- // Storage cleared but MSAL account exists - clear MSAL state
303
- instance.logoutRedirect().catch(function () { });
304
- }
305
- }
306
- }, [accessToken, account, instance, options.storageKey]);
307
- // useEffect(() => {
308
- // const handleRedirect = async () => {
309
- // try {
310
- // const response = await instance.handleRedirectPromise();
311
- // if (response) {
312
- // const account = response.account;
313
- // instance.setActiveA ccount(account);
314
- // const tokenResponse = await instance.acq uireTokenSilent({
315
- // scopes,
316
- // account,
317
- // });
318
- // setToken(tokenResponse.accessToken);
319
- // setAccessToken(tokenResponse.accessToken);
320
- // setIdToken(tokenResponse.idTo ken);
321
- // options.onAuthSuccess?.(tokenR esponse.accessToken);
322
- // if (
323
- // typeof window !== "undefined" &&
324
- // process.env.NODE_ENV !== "test"
325
- // ) {
326
- // window.location.href = options.mfaUrl!;
327
- // }
328
- // }
329
- // } catch (err) {
330
- // console.error("Redirect handling failed:", err);
331
- // }
332
- // };
333
- // handleRedirect();
334
- // }, []);
335
- var login = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
336
- var response, mfaConfig, authenticator, err_1, camsError_1, camsError;
337
- var _a, _b, _c, _d;
338
- return __generator(this, function (_e) {
339
- switch (_e.label) {
340
- case 0:
341
- setError(null);
342
- _e.label = 1;
343
- case 1:
344
- _e.trys.push([1, 3, , 4]);
345
- return [4 /*yield*/, instance.loginPopup({
346
- scopes: scopes,
347
- prompt: options.prompt || "login",
348
- })];
349
- case 2:
350
- response = _e.sent();
351
- console.log("Login Token response:", {
352
- accessToken: response.accessToken,
353
- idToken: response.idToken,
354
- });
355
- setAccessToken(response.accessToken);
356
- setIdToken(response.idToken);
357
- mfaConfig = {
358
- accessToken: response.accessToken,
359
- idToken: response.idToken,
360
- appCode: options.appCode,
361
- provider: "MSAL",
362
- apiEndpoint: options.MFAEndpoint,
363
- };
364
- authenticator = new CAMSMFAAuthenticator(mfaConfig);
365
- setMfaAuthenticator(authenticator);
366
- setRequiresMFA(true);
367
- // Don't persist as authenticated until MFA is complete
368
- if (typeof window !== "undefined") {
369
- localStorage.setItem(storageKey, JSON.stringify({
370
- isAuthenticated: false,
371
- requiresMFA: true,
372
- accessToken: response.accessToken,
373
- idToken: response.idToken,
374
- }));
375
- }
376
- (_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
377
- return [3 /*break*/, 4];
378
- case 3:
379
- err_1 = _e.sent();
380
- // Handle user cancellation gracefully
381
- if (err_1.errorCode === "user_cancelled") {
382
- Logger.error("User cancelled login");
383
- setError(null); // Don't treat cancellation as an error
384
- return [2 /*return*/];
385
- }
386
- // If popup is blocked
387
- if (err_1.errorCode === "popup_window_error" ||
388
- ((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.includes("popup"))) {
389
- camsError_1 = new CAMSError(CAMSErrorType.POPUP_BLOCKED, "Popup blocked by browser. Please allow popups and try again.");
390
- setError(camsError_1);
391
- (_c = options.onAuthError) === null || _c === void 0 ? void 0 : _c.call(options, camsError_1);
392
- return [2 /*return*/];
393
- }
394
- camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1.message || err_1);
395
- setError(camsError);
396
- (_d = options.onAuthError) === null || _d === void 0 ? void 0 : _d.call(options, camsError);
397
- return [3 /*break*/, 4];
398
- case 4: return [2 /*return*/];
399
- }
400
- });
401
- }); }, [instance, scopes, options]);
402
- var completeMFA = useCallback(function (data) { return __awaiter(_this, void 0, void 0, function () {
403
- return __generator(this, function (_a) {
404
- if (!mfaAuthenticator) {
405
- throw new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "MFA Authenticator not initialized");
406
- }
407
- Logger.info("Completed MFA.. Setting State");
408
- try {
409
- // Update storage with complete authentication BEFORE setting state
410
- if (typeof window !== "undefined") {
411
- localStorage.setItem(storageKey, JSON.stringify({
412
- isAuthenticated: true,
413
- requiresMFA: false,
414
- accessToken: accessToken,
415
- idToken: idToken,
416
- }));
417
- setUserProfile({ type: "AUTH_SUCCESS", userProfile: __assign({}, data) });
418
- setRequiresMFA(false);
419
- // Set requiresMFA to false after storage update
420
- Logger.debug("MFA completed successfully, storage updated", {
421
- accessToken: accessToken,
422
- idToken: idToken,
423
- isAuthenticated: true,
424
- requiresMFA: false,
425
- });
426
- }
427
- Logger.debug("MFA completed successfully, requiresMFA set to false");
428
- return [2 /*return*/, data];
429
- }
430
- catch (error) {
431
- setError(error);
432
- throw error;
433
- }
434
- return [2 /*return*/];
435
- });
436
- }); }, [mfaAuthenticator, accessToken, idToken, storageKey]);
437
- var sendEmailOTP = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
438
- return __generator(this, function (_a) {
439
- switch (_a.label) {
440
- case 0:
441
- if (!mfaAuthenticator) {
442
- return [2 /*return*/, false];
443
- }
444
- return [4 /*yield*/, mfaAuthenticator.sendEmailOTP()];
445
- case 1: return [2 /*return*/, _a.sent()];
446
- }
447
- });
448
- }); }, [mfaAuthenticator]);
449
- var logout = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
450
- var err_2, camsError;
451
- return __generator(this, function (_a) {
452
- switch (_a.label) {
453
- case 0:
454
- _a.trys.push([0, 2, , 3]);
455
- Logger.info("Logging User Out");
456
- return [4 /*yield*/, instance.logoutRedirect()];
457
- case 1:
458
- _a.sent();
459
- setAccessToken("");
460
- setIdToken("");
461
- setError(null);
462
- setMfaAuthenticator(null);
463
- setRequiresMFA(false);
464
- if (typeof window !== "undefined") {
465
- localStorage.removeItem(storageKey);
466
- }
467
- return [3 /*break*/, 3];
468
- case 2:
469
- err_2 = _a.sent();
470
- camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Logout failed: " + err_2);
471
- setError(camsError);
472
- return [3 /*break*/, 3];
473
- case 3: return [2 /*return*/];
474
- }
475
- });
476
- }); }, [instance, storageKey]);
477
- return {
478
- login: login,
479
- logout: logout,
480
- storageKey: storageKey,
481
- isAuthenticated: isAuthenticated,
482
- isLoading: isLoading,
483
- error: error,
484
- idToken: idToken,
485
- accessToken: accessToken,
486
- appCode: options.appCode,
487
- mfaAuthenticator: mfaAuthenticator,
488
- requiresMFA: requiresMFA,
489
- completeMFA: completeMFA,
490
- sendEmailOTP: sendEmailOTP,
491
- setRequiresMFA: setRequiresMFA,
492
- };
493
- }
494
-
495
- /**
496
- * Hook for handling authentication in popup windows
497
- * This should be used by the popup app to complete authentication
498
- */
499
- function useCAMSPopupAuth(options) {
500
- if (options === void 0) { options = {}; }
501
- var _a = options.storageKey, storageKey = _a === void 0 ? "CAMS-SDK" : _a, targetOrigin = options.targetOrigin, onAuthComplete = options.onAuthComplete, onAuthError = options.onAuthError;
502
- useEffect(function () {
503
- if (typeof window === "undefined" || !isPopupWindow())
504
- return;
505
- // Initialize popup auth handler
506
- initializePopupAuth(targetOrigin);
507
- // Set up global handlers for the popup app
508
- var globalHandlers = window.__CAMS_POPUP_AUTH__;
509
- if (globalHandlers) {
510
- var originalCompleteAuth_1 = globalHandlers.completeAuth;
511
- var originalErrorAuth_1 = globalHandlers.errorAuth;
512
- globalHandlers.completeAuth = function (profile) {
513
- onAuthComplete === null || onAuthComplete === void 0 ? void 0 : onAuthComplete(profile);
514
- originalCompleteAuth_1(profile);
515
- };
516
- globalHandlers.errorAuth = function (error) {
517
- onAuthError === null || onAuthError === void 0 ? void 0 : onAuthError(error);
518
- originalErrorAuth_1(error);
519
- };
520
- }
521
- }, [targetOrigin, onAuthComplete, onAuthError]);
522
- var completeAuth = useCallback(function (profile) {
523
- if (!isPopupWindow()) {
524
- console.warn("completeAuth called outside of popup window");
525
- return;
526
- }
527
- var sessionManager = new CAMSSessionManager(localStorage, storageKey);
528
- sessionManager.completePopupAuth(profile, targetOrigin);
529
- }, [storageKey, targetOrigin]);
530
- var errorAuth = useCallback(function (error) {
531
- if (!isPopupWindow()) {
532
- console.warn("errorAuth called outside of popup window");
533
- return;
534
- }
535
- var sessionManager = new CAMSSessionManager(localStorage, storageKey);
536
- sessionManager.errorPopupAuth(error, targetOrigin);
537
- }, [storageKey, targetOrigin]);
538
- return {
539
- completeAuth: completeAuth,
540
- errorAuth: errorAuth,
541
- isPopup: isPopupWindow(),
542
- };
543
- }
544
-
545
- var jsxRuntime = {exports: {}};
546
-
547
- var reactJsxRuntime_production = {};
241
+ var reactJsxRuntime_production = {};
548
242
 
549
243
  /**
550
244
  * @license React
@@ -953,14 +647,461 @@ function requireReactJsxRuntime_development () {
953
647
  return reactJsxRuntime_development;
954
648
  }
955
649
 
956
- if (process.env.NODE_ENV === 'production') {
957
- jsxRuntime.exports = requireReactJsxRuntime_production();
958
- } else {
959
- jsxRuntime.exports = requireReactJsxRuntime_development();
650
+ if (process.env.NODE_ENV === 'production') {
651
+ jsxRuntime.exports = requireReactJsxRuntime_production();
652
+ } else {
653
+ jsxRuntime.exports = requireReactJsxRuntime_development();
654
+ }
655
+
656
+ var jsxRuntimeExports = jsxRuntime.exports;
657
+
658
+ var CAMSContext$1 = createContext(null);
659
+ function useCAMSContext$1() {
660
+ var context = useContext(CAMSContext$1);
661
+ if (!context) {
662
+ throw new Error("useCAMSContext must be used within a UnifiedCAMSProvider");
663
+ }
664
+ return context;
665
+ }
666
+
667
+ var ClientOnly = function (_a) {
668
+ var children = _a.children, _b = _a.fallback, fallback = _b === void 0 ? null : _b;
669
+ var _c = useState(false), hasMounted = _c[0], setHasMounted = _c[1];
670
+ useEffect(function () {
671
+ setHasMounted(true);
672
+ }, []);
673
+ if (!hasMounted) {
674
+ return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: fallback });
675
+ }
676
+ return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
677
+ };
678
+
679
+ var GuidSchema = z.uuid("appCode must be a valid GUID");
680
+ var setCookie$1 = function (name, value, days) {
681
+ if (days === void 0) { days = 1; }
682
+ var expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
683
+ document.cookie = "".concat(name, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/; samesite=Lax");
684
+ };
685
+ var getCookie$1 = function (name) {
686
+ var _a;
687
+ return ((_a = document.cookie
688
+ .split("; ")
689
+ .find(function (row) { return row.startsWith(name + "="); })) === null || _a === void 0 ? void 0 : _a.split("=")[1])
690
+ ? decodeURIComponent(document.cookie
691
+ .split("; ")
692
+ .find(function (row) { return row.startsWith(name + "="); })
693
+ .split("=")[1])
694
+ : null;
695
+ };
696
+ var deleteCookie$1 = function (name) {
697
+ document.cookie = name + "=; Max-Age=-99999999; path=/";
698
+ };
699
+ function CAMSProviderCore(props) {
700
+ var _this = this;
701
+ var children = props.children, mode = props.mode, appCode = props.appCode;
702
+ // Always call both hooks to satisfy Rules of Hooks
703
+ var regularAuth = useCAMSAuth(mode === "REGULAR"
704
+ ? __assign(__assign({}, props), { appCode: appCode })
705
+ : { appCode: "" });
706
+ var msalAuth = useCAMSMSALAuth(mode === "MSAL"
707
+ ? __assign(__assign({}, props), { appCode: appCode })
708
+ : { appCode: "" });
709
+ var auth = mode === "REGULAR" ? regularAuth : msalAuth;
710
+ var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
711
+ var getInitialProfile = function () {
712
+ if (typeof window === "undefined")
713
+ return null;
714
+ try {
715
+ var storedProfile = getCookie$1(profileStorageKey);
716
+ return storedProfile ? JSON.parse(storedProfile) : null;
717
+ }
718
+ catch (_a) {
719
+ return null;
720
+ }
721
+ };
722
+ var _a = useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
723
+ useEffect(function () {
724
+ if (typeof window !== "undefined") {
725
+ var storedProfile = getCookie$1(profileStorageKey);
726
+ if (storedProfile) {
727
+ try {
728
+ setUserProfile(JSON.parse(storedProfile));
729
+ }
730
+ catch (_a) { }
731
+ }
732
+ }
733
+ }, [profileStorageKey]);
734
+ useEffect(function () {
735
+ if (typeof window !== "undefined") {
736
+ if (userProfile) {
737
+ setCookie$1(profileStorageKey, JSON.stringify(userProfile), 1);
738
+ }
739
+ else {
740
+ deleteCookie$1(profileStorageKey);
741
+ }
742
+ }
743
+ }, [userProfile, profileStorageKey]);
744
+ var enhancedLogout = function () { return __awaiter(_this, void 0, void 0, function () {
745
+ return __generator(this, function (_a) {
746
+ switch (_a.label) {
747
+ case 0: return [4 /*yield*/, auth.logout()];
748
+ case 1:
749
+ _a.sent();
750
+ setUserProfile(null);
751
+ if (typeof window !== "undefined") {
752
+ deleteCookie$1(profileStorageKey);
753
+ }
754
+ return [2 /*return*/];
755
+ }
756
+ });
757
+ }); };
758
+ // Handle MFA completion for MSAL mode
759
+ useEffect(function () {
760
+ if (mode === "MSAL" &&
761
+ "requiresMFA" in auth &&
762
+ !auth.requiresMFA &&
763
+ auth.isAuthenticated) {
764
+ // MFA completed, extract profile from localStorage
765
+ var storedData = localStorage.getItem(auth.storageKey);
766
+ console.log("MFA Complete - Checking for profile:", storedData);
767
+ if (storedData) {
768
+ try {
769
+ var parsed = JSON.parse(storedData);
770
+ console.log("Parsed storage data:", parsed);
771
+ if (parsed.userProfile) {
772
+ console.log("Setting user profile:", parsed.userProfile);
773
+ setUserProfile(parsed.userProfile);
774
+ }
775
+ }
776
+ catch (e) {
777
+ console.error("Error parsing stored data:", e);
778
+ }
779
+ }
780
+ }
781
+ }, [
782
+ mode,
783
+ "requiresMFA" in auth ? auth.requiresMFA : false,
784
+ auth.isAuthenticated,
785
+ auth.storageKey,
786
+ userProfile,
787
+ ]);
788
+ var value = useMemo(function () {
789
+ return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
790
+ }, [auth, userProfile, mode]);
791
+ return jsxRuntimeExports.jsx(CAMSContext$1.Provider, { value: value, children: children });
792
+ }
793
+ function UnifiedCAMSProvider(props) {
794
+ // Validate appCode is a valid GUID
795
+ var appCodeValidation = GuidSchema.safeParse(props.appCode);
796
+ if (!appCodeValidation.success) {
797
+ throw new Error("Invalid appCode: ".concat(appCodeValidation.error.issues[0].message));
798
+ }
799
+ if (props.mode === "MSAL") {
800
+ var msalConfig = props.msalConfig, msalInstance = props.msalInstance;
801
+ var instance = msalInstance || new PublicClientApplication(msalConfig);
802
+ return (jsxRuntimeExports.jsx(MsalProvider, { instance: instance, children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
803
+ }
804
+ return (jsxRuntimeExports.jsx(ClientOnly, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
805
+ }
806
+ // Backward compatibility exports
807
+ var CAMSProvider = function (props) { return (jsxRuntimeExports.jsx(UnifiedCAMSProvider, __assign({}, props, { mode: "REGULAR" }))); };
808
+
809
+ function useCAMSMSALAuth(options) {
810
+ var _this = this;
811
+ var storageKey = options.storageKey || "CAMS-MSAL-AUTH-SDK";
812
+ var _a = useMsal(), instance = _a.instance, inProgress = _a.inProgress, accounts = _a.accounts;
813
+ var account = useAccount(accounts[0] || {});
814
+ var _b = useState(null), error = _b[0], setError = _b[1];
815
+ var _c = useState(""), idToken = _c[0], setIdToken = _c[1];
816
+ var _d = useState(""), accessToken = _d[0], setAccessToken = _d[1];
817
+ var _e = useState(null), mfaAuthenticator = _e[0], setMfaAuthenticator = _e[1];
818
+ var _f = useState(false), requiresMFA = _f[0], setRequiresMFA = _f[1];
819
+ var isLoading = inProgress !== InteractionStatus.None;
820
+ var isAuthenticated = !!account && !!accessToken && !requiresMFA;
821
+ var scopes = options.scopes || ["openid", "profile", "email"];
822
+ var isTokenValid = function (token) {
823
+ try {
824
+ var payload = JSON.parse(atob(token.split(".")[1]));
825
+ return payload.exp * 1000 > Date.now();
826
+ }
827
+ catch (_a) {
828
+ return false;
829
+ }
830
+ };
831
+ useEffect(function () {
832
+ if (typeof window !== "undefined" && !accessToken) {
833
+ var stored = localStorage.getItem(storageKey);
834
+ if (stored) {
835
+ try {
836
+ var _a = JSON.parse(stored), accessToken_1 = _a.accessToken, idToken_1 = _a.idToken, storedRequiresMFA = _a.requiresMFA, storedIsAuthenticated = _a.isAuthenticated;
837
+ if (accessToken_1 && isTokenValid(accessToken_1)) {
838
+ setAccessToken(accessToken_1);
839
+ setIdToken(idToken_1);
840
+ // Restore MFA state
841
+ if (storedRequiresMFA && !storedIsAuthenticated) {
842
+ var mfaConfig = {
843
+ accessToken: accessToken_1,
844
+ idToken: idToken_1,
845
+ appCode: options.appCode,
846
+ provider: "MSAL",
847
+ apiEndpoint: options.MFAEndpoint,
848
+ };
849
+ var authenticator = new CAMSMFAAuthenticator(mfaConfig);
850
+ setMfaAuthenticator(authenticator);
851
+ setRequiresMFA(true);
852
+ }
853
+ Logger.debug("App Code", { ">>>": options.appCode });
854
+ }
855
+ else {
856
+ localStorage.removeItem(storageKey);
857
+ }
858
+ }
859
+ catch (_b) { }
860
+ }
861
+ else if (account) {
862
+ // Storage cleared but MSAL account exists - clear MSAL state
863
+ instance.logoutRedirect().catch(function () { });
864
+ }
865
+ }
866
+ }, [accessToken, account, instance, options.storageKey]);
867
+ // useEffect(() => {
868
+ // const handleRedirect = async () => {
869
+ // try {
870
+ // const response = await instance.handleRedirectPromise();
871
+ // if (response) {
872
+ // const account = response.account;
873
+ // instance.setActiveA ccount(account);
874
+ // const tokenResponse = await instance.acq uireTokenSilent({
875
+ // scopes,
876
+ // account,
877
+ // });
878
+ // setToken(tokenResponse.accessToken);
879
+ // setAccessToken(tokenResponse.accessToken);
880
+ // setIdToken(tokenResponse.idTo ken);
881
+ // options.onAuthSuccess?.(tokenR esponse.accessToken);
882
+ // if (
883
+ // typeof window !== "undefined" &&
884
+ // process.env.NODE_ENV !== "test"
885
+ // ) {
886
+ // window.location.href = options.mfaUrl!;
887
+ // }
888
+ // }
889
+ // } catch (err) {
890
+ // console.error("Redirect handling failed:", err);
891
+ // }
892
+ // };
893
+ // handleRedirect();
894
+ // }, []);
895
+ var login = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
896
+ var response, mfaConfig, authenticator, err_1, camsError_1, camsError;
897
+ var _a, _b, _c, _d;
898
+ return __generator(this, function (_e) {
899
+ switch (_e.label) {
900
+ case 0:
901
+ setError(null);
902
+ _e.label = 1;
903
+ case 1:
904
+ _e.trys.push([1, 3, , 4]);
905
+ return [4 /*yield*/, instance.loginPopup({
906
+ scopes: scopes,
907
+ prompt: options.prompt || "login",
908
+ })];
909
+ case 2:
910
+ response = _e.sent();
911
+ console.log("Login Token response:", {
912
+ accessToken: response.accessToken,
913
+ idToken: response.idToken,
914
+ });
915
+ setAccessToken(response.accessToken);
916
+ setIdToken(response.idToken);
917
+ mfaConfig = {
918
+ accessToken: response.accessToken,
919
+ idToken: response.idToken,
920
+ appCode: options.appCode,
921
+ provider: "MSAL",
922
+ apiEndpoint: options.MFAEndpoint,
923
+ };
924
+ authenticator = new CAMSMFAAuthenticator(mfaConfig);
925
+ setMfaAuthenticator(authenticator);
926
+ setRequiresMFA(true);
927
+ // Don't persist as authenticated until MFA is complete
928
+ if (typeof window !== "undefined") {
929
+ localStorage.setItem(storageKey, JSON.stringify({
930
+ isAuthenticated: false,
931
+ requiresMFA: true,
932
+ accessToken: response.accessToken,
933
+ idToken: response.idToken,
934
+ }));
935
+ }
936
+ (_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
937
+ return [3 /*break*/, 4];
938
+ case 3:
939
+ err_1 = _e.sent();
940
+ // Handle user cancellation gracefully
941
+ if (err_1.errorCode === "user_cancelled") {
942
+ Logger.error("User cancelled login");
943
+ setError(null); // Don't treat cancellation as an error
944
+ return [2 /*return*/];
945
+ }
946
+ // If popup is blocked
947
+ if (err_1.errorCode === "popup_window_error" ||
948
+ ((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.includes("popup"))) {
949
+ camsError_1 = new CAMSError(CAMSErrorType.POPUP_BLOCKED, "Popup blocked by browser. Please allow popups and try again.");
950
+ setError(camsError_1);
951
+ (_c = options.onAuthError) === null || _c === void 0 ? void 0 : _c.call(options, camsError_1);
952
+ return [2 /*return*/];
953
+ }
954
+ camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1.message || err_1);
955
+ setError(camsError);
956
+ (_d = options.onAuthError) === null || _d === void 0 ? void 0 : _d.call(options, camsError);
957
+ return [3 /*break*/, 4];
958
+ case 4: return [2 /*return*/];
959
+ }
960
+ });
961
+ }); }, [instance, scopes, options]);
962
+ var completeMFA = useCallback(function (data) { return __awaiter(_this, void 0, void 0, function () {
963
+ return __generator(this, function (_a) {
964
+ if (!mfaAuthenticator) {
965
+ throw new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "MFA Authenticator not initialized");
966
+ }
967
+ Logger.info("Completed MFA.. Setting State");
968
+ try {
969
+ // Update storage with complete authentication BEFORE setting state
970
+ if (typeof window !== "undefined") {
971
+ localStorage.setItem(storageKey, JSON.stringify({
972
+ isAuthenticated: true,
973
+ requiresMFA: false,
974
+ accessToken: accessToken,
975
+ idToken: idToken,
976
+ }));
977
+ setCookie$1("CAMS-MSAL-AUTH-SDK-PROFILE", JSON.stringify({ type: "AUTH_SUCCESS", userProfile: __assign({}, data) }), 1);
978
+ setRequiresMFA(false);
979
+ // Set requiresMFA to false after storage update
980
+ Logger.debug("MFA completed successfully, storage updated", {
981
+ accessToken: accessToken,
982
+ idToken: idToken,
983
+ isAuthenticated: true,
984
+ requiresMFA: false,
985
+ });
986
+ }
987
+ Logger.debug("MFA completed successfully, requiresMFA set to false");
988
+ return [2 /*return*/, data];
989
+ }
990
+ catch (error) {
991
+ setError(error);
992
+ throw error;
993
+ }
994
+ return [2 /*return*/];
995
+ });
996
+ }); }, [mfaAuthenticator, accessToken, idToken, storageKey]);
997
+ var sendEmailOTP = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
998
+ return __generator(this, function (_a) {
999
+ switch (_a.label) {
1000
+ case 0:
1001
+ if (!mfaAuthenticator) {
1002
+ return [2 /*return*/, false];
1003
+ }
1004
+ return [4 /*yield*/, mfaAuthenticator.sendEmailOTP()];
1005
+ case 1: return [2 /*return*/, _a.sent()];
1006
+ }
1007
+ });
1008
+ }); }, [mfaAuthenticator]);
1009
+ var logout = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
1010
+ var err_2, camsError;
1011
+ return __generator(this, function (_a) {
1012
+ switch (_a.label) {
1013
+ case 0:
1014
+ _a.trys.push([0, 2, , 3]);
1015
+ Logger.info("Logging User Out");
1016
+ return [4 /*yield*/, instance.logoutRedirect()];
1017
+ case 1:
1018
+ _a.sent();
1019
+ setAccessToken("");
1020
+ setIdToken("");
1021
+ setError(null);
1022
+ setMfaAuthenticator(null);
1023
+ setRequiresMFA(false);
1024
+ if (typeof window !== "undefined") {
1025
+ localStorage.removeItem(storageKey);
1026
+ }
1027
+ return [3 /*break*/, 3];
1028
+ case 2:
1029
+ err_2 = _a.sent();
1030
+ camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Logout failed: " + err_2);
1031
+ setError(camsError);
1032
+ return [3 /*break*/, 3];
1033
+ case 3: return [2 /*return*/];
1034
+ }
1035
+ });
1036
+ }); }, [instance, storageKey]);
1037
+ return {
1038
+ login: login,
1039
+ logout: logout,
1040
+ storageKey: storageKey,
1041
+ isAuthenticated: isAuthenticated,
1042
+ isLoading: isLoading,
1043
+ error: error,
1044
+ idToken: idToken,
1045
+ accessToken: accessToken,
1046
+ appCode: options.appCode,
1047
+ mfaAuthenticator: mfaAuthenticator,
1048
+ requiresMFA: requiresMFA,
1049
+ completeMFA: completeMFA,
1050
+ sendEmailOTP: sendEmailOTP,
1051
+ setRequiresMFA: setRequiresMFA,
1052
+ };
1053
+ }
1054
+
1055
+ /**
1056
+ * Hook for handling authentication in popup windows
1057
+ * This should be used by the popup app to complete authentication
1058
+ */
1059
+ function useCAMSPopupAuth(options) {
1060
+ if (options === void 0) { options = {}; }
1061
+ var _a = options.storageKey, storageKey = _a === void 0 ? "CAMS-SDK" : _a, targetOrigin = options.targetOrigin, onAuthComplete = options.onAuthComplete, onAuthError = options.onAuthError;
1062
+ useEffect(function () {
1063
+ if (typeof window === "undefined" || !isPopupWindow())
1064
+ return;
1065
+ // Initialize popup auth handler
1066
+ initializePopupAuth(targetOrigin);
1067
+ // Set up global handlers for the popup app
1068
+ var globalHandlers = window.__CAMS_POPUP_AUTH__;
1069
+ if (globalHandlers) {
1070
+ var originalCompleteAuth_1 = globalHandlers.completeAuth;
1071
+ var originalErrorAuth_1 = globalHandlers.errorAuth;
1072
+ globalHandlers.completeAuth = function (profile) {
1073
+ onAuthComplete === null || onAuthComplete === void 0 ? void 0 : onAuthComplete(profile);
1074
+ originalCompleteAuth_1(profile);
1075
+ };
1076
+ globalHandlers.errorAuth = function (error) {
1077
+ onAuthError === null || onAuthError === void 0 ? void 0 : onAuthError(error);
1078
+ originalErrorAuth_1(error);
1079
+ };
1080
+ }
1081
+ }, [targetOrigin, onAuthComplete, onAuthError]);
1082
+ var completeAuth = useCallback(function (profile) {
1083
+ if (!isPopupWindow()) {
1084
+ console.warn("completeAuth called outside of popup window");
1085
+ return;
1086
+ }
1087
+ var sessionManager = new CAMSSessionManager(localStorage, storageKey);
1088
+ sessionManager.completePopupAuth(profile, targetOrigin);
1089
+ }, [storageKey, targetOrigin]);
1090
+ var errorAuth = useCallback(function (error) {
1091
+ if (!isPopupWindow()) {
1092
+ console.warn("errorAuth called outside of popup window");
1093
+ return;
1094
+ }
1095
+ var sessionManager = new CAMSSessionManager(localStorage, storageKey);
1096
+ sessionManager.errorPopupAuth(error, targetOrigin);
1097
+ }, [storageKey, targetOrigin]);
1098
+ return {
1099
+ completeAuth: completeAuth,
1100
+ errorAuth: errorAuth,
1101
+ isPopup: isPopupWindow(),
1102
+ };
960
1103
  }
961
1104
 
962
- var jsxRuntimeExports = jsxRuntime.exports;
963
-
964
1105
  var CAMSContext = createContext(null);
965
1106
  function useCAMSContext() {
966
1107
  var context = useContext(CAMSContext);
@@ -987,11 +1128,11 @@ function ProtectedRoute(_a) {
987
1128
  }
988
1129
 
989
1130
  var CAMSMSALContext = createContext(null);
990
- var setCookie$1 = function (name, value, days) {
1131
+ var setCookie = function (name, value, days) {
991
1132
  var expires = new Date(Date.now() + days * 864e5).toUTCString();
992
1133
  document.cookie = "".concat(name, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/; samesite=Lax");
993
1134
  };
994
- var getCookie$1 = function (name) {
1135
+ var getCookie = function (name) {
995
1136
  var _a;
996
1137
  return ((_a = document.cookie
997
1138
  .split("; ")
@@ -1002,7 +1143,7 @@ var getCookie$1 = function (name) {
1002
1143
  .split("=")[1])
1003
1144
  : null;
1004
1145
  };
1005
- var deleteCookie$1 = function (name) {
1146
+ var deleteCookie = function (name) {
1006
1147
  document.cookie = name + "=; Max-Age=-99999999; path=/";
1007
1148
  };
1008
1149
  var isTokenValid = function (token) {
@@ -1024,7 +1165,7 @@ function CAMSMSALProviderInner(_a) {
1024
1165
  return null;
1025
1166
  }
1026
1167
  try {
1027
- var storedProfile = getCookie$1(profileStorageKey);
1168
+ var storedProfile = getCookie(profileStorageKey);
1028
1169
  return storedProfile ? JSON.parse(storedProfile) : null;
1029
1170
  }
1030
1171
  catch (_a) {
@@ -1036,7 +1177,7 @@ function CAMSMSALProviderInner(_a) {
1036
1177
  useEffect(function () {
1037
1178
  if (typeof window !== "undefined") {
1038
1179
  // const storedProfile = localStorage.get Item(profileStorageKey);
1039
- var storedProfile = getCookie$1(profileStorageKey);
1180
+ var storedProfile = getCookie(profileStorageKey);
1040
1181
  if (storedProfile) {
1041
1182
  try {
1042
1183
  setUserProfile(JSON.parse(storedProfile));
@@ -1061,10 +1202,10 @@ function CAMSMSALProviderInner(_a) {
1061
1202
  useEffect(function () {
1062
1203
  if (typeof window !== "undefined") {
1063
1204
  if (userProfile) {
1064
- setCookie$1(profileStorageKey, JSON.stringify(userProfile), 1); // Store for 1 day
1205
+ setCookie(profileStorageKey, JSON.stringify(userProfile), 1); // Store for 1 day
1065
1206
  }
1066
1207
  else {
1067
- deleteCookie$1(profileStorageKey);
1208
+ deleteCookie(profileStorageKey);
1068
1209
  }
1069
1210
  }
1070
1211
  }, [userProfile, profileStorageKey]);
@@ -1077,7 +1218,7 @@ function CAMSMSALProviderInner(_a) {
1077
1218
  _a.sent();
1078
1219
  setUserProfile(null);
1079
1220
  if (typeof window !== "undefined") {
1080
- deleteCookie$1(profileStorageKey);
1221
+ deleteCookie(profileStorageKey);
1081
1222
  }
1082
1223
  return [2 /*return*/];
1083
1224
  }
@@ -1099,147 +1240,6 @@ function useCAMSMSALContext() {
1099
1240
  return context;
1100
1241
  }
1101
1242
 
1102
- var ClientOnly = function (_a) {
1103
- var children = _a.children, _b = _a.fallback, fallback = _b === void 0 ? null : _b;
1104
- var _c = useState(false), hasMounted = _c[0], setHasMounted = _c[1];
1105
- useEffect(function () {
1106
- setHasMounted(true);
1107
- }, []);
1108
- if (!hasMounted) {
1109
- return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: fallback });
1110
- }
1111
- return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
1112
- };
1113
-
1114
- var GuidSchema = z.uuid("appCode must be a valid GUID");
1115
- var setCookie = function (name, value, days) {
1116
- var expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
1117
- document.cookie = "".concat(name, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/; samesite=Lax");
1118
- };
1119
- var getCookie = function (name) {
1120
- var _a;
1121
- return ((_a = document.cookie
1122
- .split("; ")
1123
- .find(function (row) { return row.startsWith(name + "="); })) === null || _a === void 0 ? void 0 : _a.split("=")[1])
1124
- ? decodeURIComponent(document.cookie
1125
- .split("; ")
1126
- .find(function (row) { return row.startsWith(name + "="); })
1127
- .split("=")[1])
1128
- : null;
1129
- };
1130
- var deleteCookie = function (name) {
1131
- document.cookie = name + "=; Max-Age=-99999999; path=/";
1132
- };
1133
- function CAMSProviderCore(props) {
1134
- var _this = this;
1135
- var children = props.children, mode = props.mode, appCode = props.appCode;
1136
- // Always call both hooks to satisfy Rules of Hooks
1137
- var regularAuth = useCAMSAuth(mode === "REGULAR"
1138
- ? __assign(__assign({}, props), { appCode: appCode })
1139
- : { appCode: "" });
1140
- var msalAuth = useCAMSMSALAuth(mode === "MSAL"
1141
- ? __assign(__assign({}, props), { appCode: appCode })
1142
- : { appCode: "" });
1143
- var auth = mode === "REGULAR" ? regularAuth : msalAuth;
1144
- var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
1145
- var getInitialProfile = function () {
1146
- if (typeof window === "undefined")
1147
- return null;
1148
- try {
1149
- var storedProfile = getCookie(profileStorageKey);
1150
- return storedProfile ? JSON.parse(storedProfile) : null;
1151
- }
1152
- catch (_a) {
1153
- return null;
1154
- }
1155
- };
1156
- var _a = useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
1157
- useEffect(function () {
1158
- if (typeof window !== "undefined") {
1159
- var storedProfile = getCookie(profileStorageKey);
1160
- if (storedProfile) {
1161
- try {
1162
- setUserProfile(JSON.parse(storedProfile));
1163
- }
1164
- catch (_a) { }
1165
- }
1166
- }
1167
- }, [profileStorageKey]);
1168
- useEffect(function () {
1169
- if (typeof window !== "undefined") {
1170
- if (userProfile) {
1171
- setCookie(profileStorageKey, JSON.stringify(userProfile), 1);
1172
- }
1173
- else {
1174
- deleteCookie(profileStorageKey);
1175
- }
1176
- }
1177
- }, [userProfile, profileStorageKey]);
1178
- var enhancedLogout = function () { return __awaiter(_this, void 0, void 0, function () {
1179
- return __generator(this, function (_a) {
1180
- switch (_a.label) {
1181
- case 0: return [4 /*yield*/, auth.logout()];
1182
- case 1:
1183
- _a.sent();
1184
- setUserProfile(null);
1185
- if (typeof window !== "undefined") {
1186
- deleteCookie(profileStorageKey);
1187
- }
1188
- return [2 /*return*/];
1189
- }
1190
- });
1191
- }); };
1192
- // Handle MFA completion for MSAL mode
1193
- useEffect(function () {
1194
- if (mode === "MSAL" &&
1195
- "requiresMFA" in auth &&
1196
- !auth.requiresMFA &&
1197
- auth.isAuthenticated) {
1198
- // MFA completed, extract profile from localStorage
1199
- var storedData = localStorage.getItem(auth.storageKey);
1200
- console.log("MFA Complete - Checking for profile:", storedData);
1201
- if (storedData) {
1202
- try {
1203
- var parsed = JSON.parse(storedData);
1204
- console.log("Parsed storage data:", parsed);
1205
- if (parsed.userProfile) {
1206
- console.log("Setting user profile:", parsed.userProfile);
1207
- setUserProfile(parsed.userProfile);
1208
- }
1209
- }
1210
- catch (e) {
1211
- console.error("Error parsing stored data:", e);
1212
- }
1213
- }
1214
- }
1215
- }, [
1216
- mode,
1217
- "requiresMFA" in auth ? auth.requiresMFA : false,
1218
- auth.isAuthenticated,
1219
- auth.storageKey,
1220
- userProfile,
1221
- ]);
1222
- var value = useMemo(function () {
1223
- return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
1224
- }, [auth, userProfile, mode]);
1225
- return jsxRuntimeExports.jsx(CAMSContext$1.Provider, { value: value, children: children });
1226
- }
1227
- function UnifiedCAMSProvider(props) {
1228
- // Validate appCode is a valid GUID
1229
- var appCodeValidation = GuidSchema.safeParse(props.appCode);
1230
- if (!appCodeValidation.success) {
1231
- throw new Error("Invalid appCode: ".concat(appCodeValidation.error.issues[0].message));
1232
- }
1233
- if (props.mode === "MSAL") {
1234
- var msalConfig = props.msalConfig, msalInstance = props.msalInstance;
1235
- var instance = msalInstance || new PublicClientApplication(msalConfig);
1236
- return (jsxRuntimeExports.jsx(MsalProvider, { instance: instance, children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
1237
- }
1238
- return (jsxRuntimeExports.jsx(ClientOnly, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
1239
- }
1240
- // Backward compatibility exports
1241
- var CAMSProvider = function (props) { return (jsxRuntimeExports.jsx(UnifiedCAMSProvider, __assign({}, props, { mode: "REGULAR" }))); };
1242
-
1243
1243
  /** A special constant with type `never` */
1244
1244
  function $constructor(name, initializer, params) {
1245
1245
  function init(inst, def) {
@@ -1924,5 +1924,5 @@ var MFAGate = function (_a) {
1924
1924
  return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
1925
1925
  };
1926
1926
 
1927
- export { CAMSMSALProvider, CAMSProvider, ClientOnly, DefaultLoginPage as LoginButton, MFAGate, MFAOptions, ProtectedRoute, UnifiedCAMSProvider, useCAMSAuth, useCAMSContext$1 as useCAMSContext, useCAMSMSALAuth, useCAMSMSALContext, useCAMSPopupAuth };
1927
+ export { CAMSMSALProvider, CAMSProvider, ClientOnly, DefaultLoginPage as LoginButton, MFAGate, MFAOptions, ProtectedRoute, UnifiedCAMSProvider, setCookie$1 as setCookie, useCAMSAuth, useCAMSContext$1 as useCAMSContext, useCAMSMSALAuth, useCAMSMSALContext, useCAMSPopupAuth };
1928
1928
  //# sourceMappingURL=index.esm.js.map