@nibssplc/cams-sdk-react 0.0.1-beta.63 → 0.0.1-beta.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
- export declare const useOTPHandler: ({ provider, accessToken, idToken, appCode, authenticationType, apiEndpoint, onAuthComplete, }: {
1
+ export declare const useOTPHandler: ({ provider, accessToken, idToken, appCode, authenticationType, MFAEndpoint, onAuthComplete, }: {
2
2
  provider: string;
3
3
  accessToken: string;
4
4
  idToken: string;
5
5
  appCode: string;
6
6
  authenticationType: "AuthenticatorCode" | "EmailOTP" | null;
7
- apiEndpoint?: string;
7
+ MFAEndpoint?: string;
8
8
  onAuthComplete: (state: boolean, data: UserValidatedResponse | null) => void;
9
9
  }) => {
10
10
  handleSubmitOTP: (authenticationValue: string) => Promise<boolean>;
package/dist/index.cjs.js CHANGED
@@ -1230,7 +1230,7 @@ function CAMSProviderCore(props) {
1230
1230
  }, [mode, auth, userProfile]);
1231
1231
  var value = React.useMemo(function () {
1232
1232
  return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
1233
- }, [auth, userProfile, mode]);
1233
+ }, [auth, userProfile, mode, mode === "MSAL" && "requiresMFA" in auth ? auth.requiresMFA : null]);
1234
1234
  return jsxRuntimeExports.jsx(CAMSContext.Provider, { value: value, children: children });
1235
1235
  }
1236
1236
  function UnifiedCAMSProvider(props) {
@@ -1592,8 +1592,48 @@ var AuthSuccessAnimation = function (_a) {
1592
1592
  return (jsxRuntimeExports.jsxs(framerMotion.motion.div, { initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, transition: { duration: 0.5, ease: "easeOut" }, className: "flex flex-col items-center justify-center space-y-6 p-8", onAnimationComplete: onComplete, children: [jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { scale: 0 }, animate: { scale: 1 }, transition: { delay: 0.2, duration: 0.6, type: "spring", stiffness: 200 }, children: jsxRuntimeExports.jsx(lucideReact.CheckCircle, { className: "w-20 h-20 text-green-500" }) }), jsxRuntimeExports.jsxs(framerMotion.motion.div, { initial: { y: 20, opacity: 0 }, animate: { y: 0, opacity: 1 }, transition: { delay: 0.4, duration: 0.5 }, className: "text-center space-y-2", children: [jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold text-green-600", children: "Authentication Successful!" }), jsxRuntimeExports.jsx("p", { className: "text-gray-600", children: "Redirecting you to the application..." })] }), jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { width: 0 }, animate: { width: "100%" }, transition: { delay: 0.8, duration: 2 }, className: "h-1 bg-green-500 rounded-full max-w-xs" })] }));
1593
1593
  };
1594
1594
 
1595
+ // Function to parse userAgent and generate a device ID
1596
+ var GenerateDeviceId = function () {
1597
+ var _a;
1598
+ if (typeof window === "undefined" || !window.navigator) {
1599
+ return "unknown-device";
1600
+ }
1601
+ var userAgent = window.navigator.userAgent;
1602
+ var deviceId = "";
1603
+ // Parse browser, version, OS, and device type
1604
+ var browserMatch = Array.from(userAgent.matchAll(/(Chrome|Firefox|Safari|Edge|Opera)\/([\d.]+)/ig));
1605
+ var osMatch = Array.from(userAgent.matchAll(/\(([^)]+)\)/g));
1606
+ var isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent);
1607
+ // Browser info
1608
+ if (browserMatch.length > 0) {
1609
+ var _b = browserMatch[0], browserName = _b[1], browserVersion = _b[2];
1610
+ var majorVersion = browserVersion.split(".")[0];
1611
+ deviceId += "".concat(browserName, "-").concat(majorVersion);
1612
+ }
1613
+ else {
1614
+ deviceId += "UnknownBrowser";
1615
+ }
1616
+ // OS info
1617
+ if (osMatch.length > 0) {
1618
+ var osInfo = osMatch[0][1]
1619
+ .split(";")[0]
1620
+ .trim()
1621
+ .replace(/[\s/()]/g, "_");
1622
+ deviceId += "_".concat(osInfo);
1623
+ }
1624
+ else {
1625
+ deviceId += "_UnknownOS";
1626
+ }
1627
+ // Device type
1628
+ deviceId += isMobile ? "_Mobile" : "_Desktop";
1629
+ // Add a simple hash of userAgent for uniqueness
1630
+ var hash = btoa(userAgent).slice(0, 8);
1631
+ deviceId += "_".concat(hash);
1632
+ return (_a = deviceId.replace(/[^a-zA-Z0-9-_]/g, "_")) !== null && _a !== void 0 ? _a : "unknown-device";
1633
+ };
1634
+
1595
1635
  var useOTPHandler = function (_a) {
1596
- var provider = _a.provider, accessToken = _a.accessToken, idToken = _a.idToken, appCode = _a.appCode, authenticationType = _a.authenticationType, apiEndpoint = _a.apiEndpoint, onAuthComplete = _a.onAuthComplete;
1636
+ var provider = _a.provider, accessToken = _a.accessToken, idToken = _a.idToken, appCode = _a.appCode, authenticationType = _a.authenticationType, MFAEndpoint = _a.MFAEndpoint, onAuthComplete = _a.onAuthComplete;
1597
1637
  var _b = React.useState(false), loading = _b[0], setLoading = _b[1];
1598
1638
  var _c = React.useState(0), attemptCount = _c[0], setAttemptCount = _c[1];
1599
1639
  var _d = React.useState(false), isMaxAttemptsReached = _d[0], setIsMaxAttemptsReached = _d[1];
@@ -1617,13 +1657,18 @@ var useOTPHandler = function (_a) {
1617
1657
  setAttemptCount(currentAttempt);
1618
1658
  if (authenticationType === null)
1619
1659
  return [2 /*return*/, false];
1620
- return [4 /*yield*/, axios.post(apiEndpoint || '/api/auth/verify-mfa', {
1660
+ return [4 /*yield*/, axios.post(MFAEndpoint || "/api/auth/verify-mfa", {
1621
1661
  provider: provider,
1622
1662
  accessToken: accessToken,
1623
1663
  idToken: idToken,
1624
1664
  authenticationType: authenticationType,
1625
1665
  MFACode: authenticationValue,
1626
1666
  appCode: appCode,
1667
+ }, {
1668
+ headers: {
1669
+ "X-Device-ID": GenerateDeviceId(),
1670
+ },
1671
+ timeout: 605000,
1627
1672
  })];
1628
1673
  case 2:
1629
1674
  response = (_a.sent()).data;
@@ -1667,7 +1712,7 @@ var useOTPHandler = function (_a) {
1667
1712
  idToken,
1668
1713
  authenticationType,
1669
1714
  onAuthComplete,
1670
- apiEndpoint,
1715
+ MFAEndpoint,
1671
1716
  attemptCount,
1672
1717
  isMaxAttemptsReached,
1673
1718
  ]);
@@ -1692,33 +1737,54 @@ var MFAOptions = function (_a) {
1692
1737
  var _d = React.useState(false), otpVisible = _d[0], setOtpVisible = _d[1];
1693
1738
  var _e = React.useState(false), showSuccessAnimation = _e[0], setShowSuccessAnimation = _e[1];
1694
1739
  var _f = React.useState(null), authType = _f[0], setAuthType = _f[1];
1740
+ var _g = React.useState(""), lastOTPCode = _g[0], setLastOTPCode = _g[1];
1695
1741
  var context = useCAMSContext();
1696
- var sendEmailOTP = (context.authMode === "MSAL" && "sendEmailOTP" in context
1742
+ var _h = context.authMode === "MSAL" && "sendEmailOTP" in context
1697
1743
  ? context
1698
- : { sendEmailOTP: null }).sendEmailOTP;
1744
+ : { sendEmailOTP: null, completeMFA: null }, sendEmailOTP = _h.sendEmailOTP, completeMFA = _h.completeMFA;
1699
1745
  var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
1700
1746
  var idToken = context.authMode === "MSAL" ? context.idToken : "";
1701
- var _g = useOTPHandler({
1747
+ var _j = useOTPHandler({
1702
1748
  accessToken: accessToken || "",
1703
1749
  idToken: idToken || "",
1704
1750
  provider: "MSAL",
1705
1751
  appCode: context.appCode || "",
1706
1752
  authenticationType: authType,
1707
- apiEndpoint: MFAEndpoint,
1708
- onAuthComplete: function (state, data) {
1709
- if (state) {
1710
- setShowSuccessAnimation(true);
1711
- sonner.toast.success(jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-green-600 bg-green-50 p-3 rounded-lg", children: [jsxRuntimeExports.jsx(lucideReact.ShieldCheck, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: "Multi-Factor Authentication Successful" })] }));
1712
- setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(true); }, 2000);
1713
- }
1714
- else {
1715
- sonner.toast.error(jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-red-600 bg-red-50 p-3 rounded-lg", children: [jsxRuntimeExports.jsx(lucideReact.ShieldClose, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: (data === null || data === void 0 ? void 0 : data.message) || "Invalid code. Please try again." })] }));
1716
- if (isMaxAttemptsReached) {
1717
- setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(false); }, 1000);
1753
+ MFAEndpoint: MFAEndpoint,
1754
+ onAuthComplete: function (state, data) { return __awaiter(void 0, void 0, void 0, function () {
1755
+ var error_1;
1756
+ return __generator(this, function (_a) {
1757
+ switch (_a.label) {
1758
+ case 0:
1759
+ if (!state) return [3 /*break*/, 5];
1760
+ if (!(completeMFA && authType && lastOTPCode)) return [3 /*break*/, 4];
1761
+ _a.label = 1;
1762
+ case 1:
1763
+ _a.trys.push([1, 3, , 4]);
1764
+ return [4 /*yield*/, completeMFA(lastOTPCode, authType)];
1765
+ case 2:
1766
+ _a.sent();
1767
+ return [3 /*break*/, 4];
1768
+ case 3:
1769
+ error_1 = _a.sent();
1770
+ console.error("Failed to complete MFA:", error_1);
1771
+ return [3 /*break*/, 4];
1772
+ case 4:
1773
+ setShowSuccessAnimation(true);
1774
+ sonner.toast.success(jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-green-600 bg-green-50 p-3 rounded-lg", children: [jsxRuntimeExports.jsx(lucideReact.ShieldCheck, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: "Multi-Factor Authentication Successful" })] }));
1775
+ setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(true); }, 2000);
1776
+ return [3 /*break*/, 6];
1777
+ case 5:
1778
+ sonner.toast.error(jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-red-600 bg-red-50 p-3 rounded-lg", children: [jsxRuntimeExports.jsx(lucideReact.ShieldClose, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: (data === null || data === void 0 ? void 0 : data.message) || "Invalid code. Please try again." })] }));
1779
+ if (isMaxAttemptsReached) {
1780
+ setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(false); }, 1000);
1781
+ }
1782
+ _a.label = 6;
1783
+ case 6: return [2 /*return*/];
1718
1784
  }
1719
- }
1720
- },
1721
- }), handleSubmitOTP = _g.handleSubmitOTP, loading = _g.loading, setLoading = _g.setLoading, attemptCount = _g.attemptCount, remainingAttempts = _g.remainingAttempts, isMaxAttemptsReached = _g.isMaxAttemptsReached, resetAttempts = _g.resetAttempts;
1785
+ });
1786
+ }); },
1787
+ }), handleSubmitOTP = _j.handleSubmitOTP, loading = _j.loading, setLoading = _j.setLoading, attemptCount = _j.attemptCount, remainingAttempts = _j.remainingAttempts, isMaxAttemptsReached = _j.isMaxAttemptsReached, resetAttempts = _j.resetAttempts;
1722
1788
  var handleGoBack = function () {
1723
1789
  setAuthType(null);
1724
1790
  setOtpVisible(false);
@@ -1727,9 +1793,9 @@ var MFAOptions = function (_a) {
1727
1793
  };
1728
1794
  // Show success animation if authentication is successful
1729
1795
  if (showSuccessAnimation) {
1730
- return (jsxRuntimeExports.jsx(Card, { className: "mx-auto space-y-6 p-6 bg-white rounded-lg shadow-md", children: jsxRuntimeExports.jsx(AuthSuccessAnimation, { onComplete: function () {
1731
- // Animation completed, can add additional logic here if needed
1732
- } }) }));
1796
+ return (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center h-dvh", children: jsxRuntimeExports.jsx(Card, { className: "mx-auto space-y-6 p-6 bg-white rounded-lg shadow-md", children: jsxRuntimeExports.jsx(AuthSuccessAnimation, { onComplete: function () {
1797
+ // Animation completed, can add additional logic here if needed
1798
+ } }) }) }));
1733
1799
  }
1734
1800
  var content = jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
1735
1801
  if (!authType) {
@@ -1765,12 +1831,18 @@ var MFAOptions = function (_a) {
1765
1831
  setAuthType(null);
1766
1832
  setOtpVisible(false);
1767
1833
  setValue("");
1768
- }, children: [jsxRuntimeExports.jsx(DialogHeader, { children: jsxRuntimeExports.jsx(DialogTitle, { children: "Email OTP" }) }), jsxRuntimeExports.jsx(DialogContent, { className: "sm:max-w-[425px]", children: jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx(GenericOTPVerifier, { value: value, setValue: setValue, isDisabled: loading || isMaxAttemptsReached, onChangeOTP: handleSubmitOTP, fieldName: "EmailOTP", attemptCount: attemptCount, remainingAttempts: remainingAttempts, isMaxAttemptsReached: isMaxAttemptsReached }), jsxRuntimeExports.jsx(Button, { variant: "ghost", className: "w-full text-sm", onClick: handleGoBack, children: "\u2190 Choose different method" })] }) })] }));
1834
+ }, children: [jsxRuntimeExports.jsx(DialogHeader, { children: jsxRuntimeExports.jsx(DialogTitle, { children: "Email OTP" }) }), jsxRuntimeExports.jsx(DialogContent, { className: "sm:max-w-[425px]", children: jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx(GenericOTPVerifier, { value: value, setValue: setValue, isDisabled: loading || isMaxAttemptsReached, onChangeOTP: function (code) {
1835
+ setLastOTPCode(code);
1836
+ return handleSubmitOTP(code);
1837
+ }, fieldName: "EmailOTP", attemptCount: attemptCount, remainingAttempts: remainingAttempts, isMaxAttemptsReached: isMaxAttemptsReached }), jsxRuntimeExports.jsx(Button, { variant: "ghost", className: "w-full text-sm", onClick: handleGoBack, children: "\u2190 Choose different method" })] }) })] }));
1769
1838
  }
1770
1839
  else if (authType === "AuthenticatorCode") {
1771
- 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 })] })) })] }));
1840
+ 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: function (code) {
1841
+ setLastOTPCode(code);
1842
+ return handleSubmitOTP(code);
1843
+ }, fieldName: "AuthenticatorCode", attemptCount: attemptCount, remainingAttempts: remainingAttempts, isMaxAttemptsReached: isMaxAttemptsReached })] })) })] }));
1772
1844
  }
1773
- 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("div", { className: "flex justify-center items", 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-base -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(lucideReact.ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
1845
+ 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("div", { className: "flex justify-center items", 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-base -tracking-wide text-center", children: "Your Microsoft account has been validated. Please complete two-factor authentication to continue." })] }), jsxRuntimeExports.jsx(CardContent, { className: "max-w-[80%]", children: content }), jsxRuntimeExports.jsxs(CardFooter, { className: "flex items-center justify-center mt-6 space-x-2 text-gray-400 text-sm", children: [jsxRuntimeExports.jsx(lucideReact.ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
1774
1846
  };
1775
1847
 
1776
1848
  var LoginButton = function () {