@nibssplc/cams-sdk-react 0.0.1-beta.60 → 0.0.1-beta.62

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
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { useState, useRef, useEffect, useCallback, createContext, useContext, useMemo } from 'react';
3
- import { isPopupWindow, initializePopupAuth, CAMSSessionManager, Logger, CAMSError, CAMSErrorType, CAMSMFAAuthenticator } from '@nibssplc/cams-sdk';
3
+ import { isPopupWindow, initializePopupAuth, CAMSSessionManager, CAMSMFAAuthenticator, Logger, CAMSError, CAMSErrorType } from '@nibssplc/cams-sdk';
4
4
  export * from '@nibssplc/cams-sdk';
5
5
  import { useMsal, useAccount, MsalProvider } from '@azure/msal-react';
6
6
  import { InteractionStatus, PublicClientApplication } from '@azure/msal-browser';
@@ -240,7 +240,7 @@ function useCAMSMSALAuth(options) {
240
240
  var _this = this;
241
241
  if (options === void 0) { options = {
242
242
  appCode: "",
243
- mfaUrl: "/auth/multi-factor",
243
+ MFAEndpoint: "/auth/multi-factor",
244
244
  storageKey: "CAMS-MSAL-AUTH-SDK",
245
245
  }; }
246
246
  var _a = useMsal(), instance = _a.instance, inProgress = _a.inProgress, accounts = _a.accounts;
@@ -267,11 +267,25 @@ function useCAMSMSALAuth(options) {
267
267
  var stored = localStorage.getItem(options.storageKey);
268
268
  if (stored) {
269
269
  try {
270
- var _a = JSON.parse(stored), accessToken_1 = _a.accessToken, idToken_1 = _a.idToken, appCode = _a.appCode;
270
+ var _a = JSON.parse(stored), accessToken_1 = _a.accessToken, idToken_1 = _a.idToken, appCode = _a.appCode, storedRequiresMFA = _a.requiresMFA, storedIsAuthenticated = _a.isAuthenticated;
271
271
  if (accessToken_1 && isTokenValid(accessToken_1)) {
272
272
  setAccessToken(accessToken_1);
273
273
  setIdToken(idToken_1);
274
+ // Restore MFA state
275
+ if (storedRequiresMFA && !storedIsAuthenticated) {
276
+ var mfaConfig = {
277
+ accessToken: accessToken_1,
278
+ idToken: idToken_1,
279
+ appCode: options.appCode,
280
+ provider: "MSAL",
281
+ apiEndpoint: options.MFAEndpoint,
282
+ };
283
+ var authenticator = new CAMSMFAAuthenticator(mfaConfig);
284
+ setMfaAuthenticator(authenticator);
285
+ setRequiresMFA(true);
286
+ }
274
287
  console.log("App Code >>>", appCode, options.appCode);
288
+ console.log("MFA Endpoint >>>", appCode, options.MFAEndpoint);
275
289
  }
276
290
  else {
277
291
  localStorage.removeItem(options.storageKey);
@@ -279,8 +293,12 @@ function useCAMSMSALAuth(options) {
279
293
  }
280
294
  catch (_b) { }
281
295
  }
296
+ else if (account) {
297
+ // Storage cleared but MSAL account exists - clear MSAL state
298
+ instance.logoutRedirect().catch(function () { });
299
+ }
282
300
  }
283
- }, [accessToken]);
301
+ }, [accessToken, account, instance, options.storageKey]);
284
302
  // useEffect(() => {
285
303
  // const handleRedirect = async () => {
286
304
  // try {
@@ -336,7 +354,7 @@ function useCAMSMSALAuth(options) {
336
354
  idToken: response.idToken,
337
355
  appCode: options.appCode,
338
356
  provider: "MSAL",
339
- apiEndpoint: options.mfaApiEndpoint,
357
+ apiEndpoint: options.MFAEndpoint,
340
358
  };
341
359
  authenticator = new CAMSMFAAuthenticator(mfaConfig);
342
360
  setMfaAuthenticator(authenticator);
@@ -1118,14 +1136,14 @@ var deleteCookie = function (name) {
1118
1136
  };
1119
1137
  function CAMSProviderCore(props) {
1120
1138
  var _this = this;
1121
- var _a = props, children = _a.children, mode = _a.mode, appCode = _a.appCode, validateTokenUrl = _a.validateTokenUrl;
1139
+ var children = props.children, mode = props.mode, appCode = props.appCode;
1122
1140
  // Always call both hooks to satisfy Rules of Hooks
1123
1141
  var regularAuth = useCAMSAuth(mode === "REGULAR"
1124
1142
  ? __assign(__assign({}, props), { appCode: appCode })
1125
1143
  : { appCode: "" });
1126
1144
  var msalAuth = useCAMSMSALAuth(mode === "MSAL"
1127
1145
  ? __assign(__assign({}, props), { appCode: appCode })
1128
- : { appCode: "" });
1146
+ : { appCode: "", MFAEndpoint: "/auth/multi-factor" });
1129
1147
  var auth = mode === "REGULAR" ? regularAuth : msalAuth;
1130
1148
  var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
1131
1149
  var getInitialProfile = function () {
@@ -1139,7 +1157,7 @@ function CAMSProviderCore(props) {
1139
1157
  return null;
1140
1158
  }
1141
1159
  };
1142
- var _b = useState(getInitialProfile), userProfile = _b[0], setUserProfile = _b[1];
1160
+ var _a = useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
1143
1161
  useEffect(function () {
1144
1162
  if (typeof window !== "undefined") {
1145
1163
  var storedProfile = getCookie(profileStorageKey);
@@ -1177,7 +1195,11 @@ function CAMSProviderCore(props) {
1177
1195
  }); };
1178
1196
  // Handle MFA completion for MSAL mode
1179
1197
  useEffect(function () {
1180
- if (mode === "MSAL" && "requiresMFA" in auth && !auth.requiresMFA && auth.isAuthenticated && !userProfile) {
1198
+ if (mode === "MSAL" &&
1199
+ "requiresMFA" in auth &&
1200
+ !auth.requiresMFA &&
1201
+ auth.isAuthenticated &&
1202
+ !userProfile) {
1181
1203
  // MFA completed, extract profile from stored data
1182
1204
  var storedData = getCookie(auth.storageKey);
1183
1205
  if (storedData) {
@@ -1192,8 +1214,8 @@ function CAMSProviderCore(props) {
1192
1214
  }
1193
1215
  }, [mode, auth, userProfile]);
1194
1216
  var value = useMemo(function () {
1195
- return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode, validateTokenUrl: validateTokenUrl }));
1196
- }, [auth, userProfile, mode, validateTokenUrl]);
1217
+ return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
1218
+ }, [auth, userProfile, mode]);
1197
1219
  return jsxRuntimeExports.jsx(CAMSContext.Provider, { value: value, children: children });
1198
1220
  }
1199
1221
  function UnifiedCAMSProvider(props) {
@@ -1202,11 +1224,11 @@ function UnifiedCAMSProvider(props) {
1202
1224
  if (!appCodeValidation.success) {
1203
1225
  throw new Error("Invalid appCode: ".concat(appCodeValidation.error.issues[0].message));
1204
1226
  }
1205
- // Validate validateTokenUrl if provided
1206
- if (props.mode === "MSAL" && props.validateTokenUrl) {
1207
- var urlValidation = UrlSchema.safeParse(props.validateTokenUrl);
1227
+ // Validate apiEndpoint if provided
1228
+ if (props.mode === "MSAL" && props.MFAEndpoint) {
1229
+ var urlValidation = UrlSchema.safeParse(props.MFAEndpoint);
1208
1230
  if (!urlValidation.success) {
1209
- throw new Error("Invalid validateTokenUrl: ".concat(urlValidation.error.issues[0].message));
1231
+ throw new Error("Invalid apiEndpoint: ".concat(urlValidation.error.issues[0].message));
1210
1232
  }
1211
1233
  }
1212
1234
  if (props.mode === "MSAL") {
@@ -1452,9 +1474,9 @@ var GenericOTPVerifier = function (_a) {
1452
1474
  resolver: a$1(Schema),
1453
1475
  defaultValues: (_c = {}, _c[fieldName] = "", _c),
1454
1476
  });
1455
- return (jsxRuntimeExports.jsxs("div", { className: "relative rounded space-y-4 p-0 m-0 py-8 space-x-6", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "flex items-center justify-center flex-col gap-2 mt-2 text-center mb-8", children: [jsxRuntimeExports.jsx("div", { className: "w-16 h-16 bg-gradient-to-br from-lime-400 via-green-500 to-emerald-600 rounded-xl flex items-center justify-center text-white text-2xl mb-6 group-hover:scale-110 transition-transform duration-300", children: jsxRuntimeExports.jsx(RectangleEllipsis, {}) }), jsxRuntimeExports.jsx(CardTitle, { className: "font-bold text-emerald-700 text-2xl", children: "One-Time-Password (OTP)" }), attemptCount > 0 && (jsxRuntimeExports.jsx("div", { className: "text-sm mt-2 ".concat(isMaxAttemptsReached ? 'text-red-600' : 'text-orange-600'), children: isMaxAttemptsReached
1477
+ return (jsxRuntimeExports.jsxs(Card, { className: "relative rounded space-y-4 p-0 m-0 py-8 space-x-6", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "flex items-center justify-center flex-col gap-2 mt-2 text-center mb-8", children: [jsxRuntimeExports.jsx("div", { className: "w-16 h-16 bg-gradient-to-br from-lime-400 via-green-500 to-emerald-600 rounded-xl flex items-center justify-center text-white text-2xl mb-6 group-hover:scale-110 transition-transform duration-300", children: jsxRuntimeExports.jsx(RectangleEllipsis, {}) }), jsxRuntimeExports.jsx(CardTitle, { className: "font-bold text-emerald-700 text-2xl", children: "One-Time-Password (OTP)" }), attemptCount > 0 && (jsxRuntimeExports.jsx("div", { className: "text-sm mt-2 ".concat(isMaxAttemptsReached ? 'text-red-600' : 'text-orange-600'), children: isMaxAttemptsReached
1456
1478
  ? 'Maximum attempts reached. Please try again later.'
1457
- : "Attempt ".concat(attemptCount, "/3 - ").concat(remainingAttempts, " attempts remaining") }))] }), jsxRuntimeExports.jsx("div", { className: "space-y-6", children: jsxRuntimeExports.jsx(Form, __assign({}, form, { children: jsxRuntimeExports.jsx("form", { className: "flex items-center justify-center my-4 ", children: jsxRuntimeExports.jsx(FormField, { control: form.control, name: fieldName, render: function () { return (jsxRuntimeExports.jsxs(FormItem, { className: "flex items-center justify-center flex-col gap-y-1 space-y-4", children: [jsxRuntimeExports.jsx(FormControl, { children: jsxRuntimeExports.jsx(InputOTP, { maxLength: 6, value: value, disabled: isMaxAttemptsReached, onChange: function (authenticationValue) {
1479
+ : "Attempt ".concat(attemptCount, "/3 - ").concat(remainingAttempts, " attempts remaining") }))] }), jsxRuntimeExports.jsx(CardContent, { className: "space-y-6", children: jsxRuntimeExports.jsx(Form, __assign({}, form, { children: jsxRuntimeExports.jsx("form", { className: "flex items-center justify-center my-4 ", children: jsxRuntimeExports.jsx(FormField, { control: form.control, name: fieldName, render: function () { return (jsxRuntimeExports.jsxs(FormItem, { className: "flex items-center justify-center flex-col gap-y-1 space-y-4", children: [jsxRuntimeExports.jsx(FormControl, { children: jsxRuntimeExports.jsx(InputOTP, { maxLength: 6, value: value, disabled: isMaxAttemptsReached, onChange: function (authenticationValue) {
1458
1480
  setValue(authenticationValue);
1459
1481
  if (authenticationValue.length === 6 && !isMaxAttemptsReached) {
1460
1482
  setLoading === null || setLoading === void 0 ? void 0 : setLoading(true);
@@ -1463,6 +1485,10 @@ var GenericOTPVerifier = function (_a) {
1463
1485
  }, pattern: REGEXP_ONLY_DIGITS, children: jsxRuntimeExports.jsx(InputOTPGroup, { className: "space-x-2", children: __spreadArray([], Array(6), true).map(function (_, idx) { return (jsxRuntimeExports.jsx(InputOTPSlot, { className: "border border-l-2 ".concat(isMaxAttemptsReached ? 'opacity-50 cursor-not-allowed' : ''), index: idx }, idx + 1)); }) }) }) }), jsxRuntimeExports.jsx(FormMessage, {})] })); } }) }) })) })] }));
1464
1486
  };
1465
1487
 
1488
+ var OTPAuthenticationImg = "OTPAuthentication.svg";
1489
+
1490
+ var MicrosoftAuthenticatorImg = "microsoftauthenticator.svg";
1491
+
1466
1492
  var buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
1467
1493
  variants: {
1468
1494
  variant: {
@@ -1660,18 +1686,18 @@ var MFAOptions = function (_a) {
1660
1686
  var _f = useState(null), authType = _f[0], setAuthType = _f[1];
1661
1687
  var context = useCAMSContext();
1662
1688
  var isSDKMode = context.authMode === "MSAL" && "completeMFA" in context;
1663
- var _g = isSDKMode
1664
- ? context
1665
- : { completeMFA: null, sendEmailOTP: null }; _g.completeMFA; var sendEmailOTP = _g.sendEmailOTP;
1689
+ var sendEmailOTP = (isSDKMode ? context : { sendEmailOTP: null }).sendEmailOTP;
1666
1690
  var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
1667
1691
  var idToken = context.authMode === "MSAL" ? context.idToken : "";
1668
- var _h = useOTPHandler({
1692
+ var _g = useOTPHandler({
1669
1693
  provider: "azure",
1670
1694
  accessToken: accessToken || "",
1671
1695
  idToken: idToken || "",
1672
1696
  appCode: context.appCode || "",
1673
1697
  authenticationType: authType,
1674
- validateTokenUrl: context.validateTokenUrl || "/api/validate-token",
1698
+ validateTokenUrl: (context.authMode === "MSAL" && "MFAEndpoint" in context
1699
+ ? context.MFAEndpoint || "/api/auth/verify-mfa"
1700
+ : "/api/validate-token"),
1675
1701
  onAuthComplete: function (success, data) {
1676
1702
  if (success) {
1677
1703
  setShowSuccessAnimation(true);
@@ -1685,7 +1711,7 @@ var MFAOptions = function (_a) {
1685
1711
  }
1686
1712
  }
1687
1713
  },
1688
- }), handleSubmitOTP = _h.handleSubmitOTP, loading = _h.loading, attemptCount = _h.attemptCount, isMaxAttemptsReached = _h.isMaxAttemptsReached, remainingAttempts = _h.remainingAttempts, resetAttempts = _h.resetAttempts;
1714
+ }), handleSubmitOTP = _g.handleSubmitOTP, loading = _g.loading, attemptCount = _g.attemptCount, isMaxAttemptsReached = _g.isMaxAttemptsReached, remainingAttempts = _g.remainingAttempts, resetAttempts = _g.resetAttempts;
1689
1715
  var handleGoBack = function () {
1690
1716
  setAuthType(null);
1691
1717
  setOtpVisible(false);
@@ -1723,7 +1749,7 @@ var MFAOptions = function (_a) {
1723
1749
  resetAttempts();
1724
1750
  setAuthType("AuthenticatorCode");
1725
1751
  setOtpVisible(true);
1726
- }, children: [jsxRuntimeExports.jsx("img", { src: "/microsoftauthenticator.svg", alt: "Authenticator", className: "rounded-full", width: 24, height: 24 }), jsxRuntimeExports.jsxs("div", { className: "text-left", children: [jsxRuntimeExports.jsx("div", { className: "font-medium", children: "Authenticator App" }), jsxRuntimeExports.jsx("div", { className: "text-sm text-gray-500", children: "Use Authenticator App" })] })] })] })] }));
1752
+ }, children: [jsxRuntimeExports.jsx("img", { src: MicrosoftAuthenticatorImg, alt: "Authenticator", className: "rounded-full", width: 24, height: 24 }), jsxRuntimeExports.jsxs("div", { className: "text-left", children: [jsxRuntimeExports.jsx("div", { className: "font-medium", children: "Authenticator App" }), jsxRuntimeExports.jsx("div", { className: "text-sm text-gray-500", children: "Use Authenticator App" })] })] })] })] }));
1727
1753
  }
1728
1754
  else if (authType === "EmailOTP") {
1729
1755
  content = (jsxRuntimeExports.jsxs(Dialog, { open: otpVisible, onOpenChange: function () {
@@ -1735,7 +1761,7 @@ var MFAOptions = function (_a) {
1735
1761
  else if (authType === "AuthenticatorCode") {
1736
1762
  content = (jsxRuntimeExports.jsxs(Dialog, { open: otpVisible, onOpenChange: handleGoBack, children: [jsxRuntimeExports.jsx(DialogHeader, { children: jsxRuntimeExports.jsx(DialogTitle, { children: "Authenticator App" }) }), jsxRuntimeExports.jsx(DialogContent, { className: "sm:max-w-[425px]", children: loading ? (jsxRuntimeExports.jsx("div", { className: "p-3 flex justify-center items-center", children: jsxRuntimeExports.jsx(LoadingSpinner, {}) })) : (jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 text-center", children: "Enter the 6-digit Code from your Authenticator app" }), jsxRuntimeExports.jsx(GenericOTPVerifier, { value: value, setValue: setValue, isDisabled: loading || isMaxAttemptsReached, onChangeOTP: handleSubmitOTP, fieldName: "AuthenticatorCode", attemptCount: attemptCount, remainingAttempts: remainingAttempts, isMaxAttemptsReached: isMaxAttemptsReached })] })) })] }));
1737
1763
  }
1738
- return (jsxRuntimeExports.jsxs(Card, { className: "mx-auto space-y-6 p-6 bg-white rounded-lg shadow-md", children: [jsxRuntimeExports.jsxs(CardHeader, { children: [jsxRuntimeExports.jsx("img", { src: "/OTPAuthentication1.svg", alt: "NIBSS Logo", width: 365, height: 365 }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold mb-6 text-center", children: "Two-Factor Authentication" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-300 text-sm -tracking-wide text-center", children: "Your Microsoft account has been validated. Please complete two-factor authentication to continue." })] }), jsxRuntimeExports.jsx(CardContent, { children: content }), jsxRuntimeExports.jsxs(CardFooter, { className: "flex items-center justify-center mt-6 space-x-2 text-gray-400 text-sm", children: [jsxRuntimeExports.jsx(ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }));
1764
+ return (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center h-dvh", children: jsxRuntimeExports.jsxs(Card, { className: "mx-auto space-y-6 p-6 bg-white rounded-lg shadow-md", children: [jsxRuntimeExports.jsxs(CardHeader, { children: [jsxRuntimeExports.jsx("img", { src: OTPAuthenticationImg, alt: "NIBSS Logo", width: 365, height: 365 }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold mb-6 text-center", children: "Two-Factor Authentication" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-300 text-sm -tracking-wide text-center", children: "Your Microsoft account has been validated. Please complete two-factor authentication to continue." })] }), jsxRuntimeExports.jsx(CardContent, { children: content }), jsxRuntimeExports.jsxs(CardFooter, { className: "flex items-center justify-center mt-6 space-x-2 text-gray-400 text-sm", children: [jsxRuntimeExports.jsx(ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
1739
1765
  };
1740
1766
 
1741
1767
  var LoginButton = function () {