@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.
- package/dist/hooks/useOTPHandler.d.ts +2 -2
- package/dist/index.cjs.js +99 -27
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +99 -27
- package/dist/index.esm.js.map +1 -1
- package/dist/utils/DeviceID.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1210,7 +1210,7 @@ function CAMSProviderCore(props) {
|
|
|
1210
1210
|
}, [mode, auth, userProfile]);
|
|
1211
1211
|
var value = useMemo(function () {
|
|
1212
1212
|
return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
|
|
1213
|
-
}, [auth, userProfile, mode]);
|
|
1213
|
+
}, [auth, userProfile, mode, mode === "MSAL" && "requiresMFA" in auth ? auth.requiresMFA : null]);
|
|
1214
1214
|
return jsxRuntimeExports.jsx(CAMSContext.Provider, { value: value, children: children });
|
|
1215
1215
|
}
|
|
1216
1216
|
function UnifiedCAMSProvider(props) {
|
|
@@ -1572,8 +1572,48 @@ var AuthSuccessAnimation = function (_a) {
|
|
|
1572
1572
|
return (jsxRuntimeExports.jsxs(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(motion.div, { initial: { scale: 0 }, animate: { scale: 1 }, transition: { delay: 0.2, duration: 0.6, type: "spring", stiffness: 200 }, children: jsxRuntimeExports.jsx(CheckCircle, { className: "w-20 h-20 text-green-500" }) }), jsxRuntimeExports.jsxs(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(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" })] }));
|
|
1573
1573
|
};
|
|
1574
1574
|
|
|
1575
|
+
// Function to parse userAgent and generate a device ID
|
|
1576
|
+
var GenerateDeviceId = function () {
|
|
1577
|
+
var _a;
|
|
1578
|
+
if (typeof window === "undefined" || !window.navigator) {
|
|
1579
|
+
return "unknown-device";
|
|
1580
|
+
}
|
|
1581
|
+
var userAgent = window.navigator.userAgent;
|
|
1582
|
+
var deviceId = "";
|
|
1583
|
+
// Parse browser, version, OS, and device type
|
|
1584
|
+
var browserMatch = Array.from(userAgent.matchAll(/(Chrome|Firefox|Safari|Edge|Opera)\/([\d.]+)/ig));
|
|
1585
|
+
var osMatch = Array.from(userAgent.matchAll(/\(([^)]+)\)/g));
|
|
1586
|
+
var isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent);
|
|
1587
|
+
// Browser info
|
|
1588
|
+
if (browserMatch.length > 0) {
|
|
1589
|
+
var _b = browserMatch[0], browserName = _b[1], browserVersion = _b[2];
|
|
1590
|
+
var majorVersion = browserVersion.split(".")[0];
|
|
1591
|
+
deviceId += "".concat(browserName, "-").concat(majorVersion);
|
|
1592
|
+
}
|
|
1593
|
+
else {
|
|
1594
|
+
deviceId += "UnknownBrowser";
|
|
1595
|
+
}
|
|
1596
|
+
// OS info
|
|
1597
|
+
if (osMatch.length > 0) {
|
|
1598
|
+
var osInfo = osMatch[0][1]
|
|
1599
|
+
.split(";")[0]
|
|
1600
|
+
.trim()
|
|
1601
|
+
.replace(/[\s/()]/g, "_");
|
|
1602
|
+
deviceId += "_".concat(osInfo);
|
|
1603
|
+
}
|
|
1604
|
+
else {
|
|
1605
|
+
deviceId += "_UnknownOS";
|
|
1606
|
+
}
|
|
1607
|
+
// Device type
|
|
1608
|
+
deviceId += isMobile ? "_Mobile" : "_Desktop";
|
|
1609
|
+
// Add a simple hash of userAgent for uniqueness
|
|
1610
|
+
var hash = btoa(userAgent).slice(0, 8);
|
|
1611
|
+
deviceId += "_".concat(hash);
|
|
1612
|
+
return (_a = deviceId.replace(/[^a-zA-Z0-9-_]/g, "_")) !== null && _a !== void 0 ? _a : "unknown-device";
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1575
1615
|
var useOTPHandler = function (_a) {
|
|
1576
|
-
var provider = _a.provider, accessToken = _a.accessToken, idToken = _a.idToken, appCode = _a.appCode, authenticationType = _a.authenticationType,
|
|
1616
|
+
var provider = _a.provider, accessToken = _a.accessToken, idToken = _a.idToken, appCode = _a.appCode, authenticationType = _a.authenticationType, MFAEndpoint = _a.MFAEndpoint, onAuthComplete = _a.onAuthComplete;
|
|
1577
1617
|
var _b = useState(false), loading = _b[0], setLoading = _b[1];
|
|
1578
1618
|
var _c = useState(0), attemptCount = _c[0], setAttemptCount = _c[1];
|
|
1579
1619
|
var _d = useState(false), isMaxAttemptsReached = _d[0], setIsMaxAttemptsReached = _d[1];
|
|
@@ -1597,13 +1637,18 @@ var useOTPHandler = function (_a) {
|
|
|
1597
1637
|
setAttemptCount(currentAttempt);
|
|
1598
1638
|
if (authenticationType === null)
|
|
1599
1639
|
return [2 /*return*/, false];
|
|
1600
|
-
return [4 /*yield*/, axios.post(
|
|
1640
|
+
return [4 /*yield*/, axios.post(MFAEndpoint || "/api/auth/verify-mfa", {
|
|
1601
1641
|
provider: provider,
|
|
1602
1642
|
accessToken: accessToken,
|
|
1603
1643
|
idToken: idToken,
|
|
1604
1644
|
authenticationType: authenticationType,
|
|
1605
1645
|
MFACode: authenticationValue,
|
|
1606
1646
|
appCode: appCode,
|
|
1647
|
+
}, {
|
|
1648
|
+
headers: {
|
|
1649
|
+
"X-Device-ID": GenerateDeviceId(),
|
|
1650
|
+
},
|
|
1651
|
+
timeout: 605000,
|
|
1607
1652
|
})];
|
|
1608
1653
|
case 2:
|
|
1609
1654
|
response = (_a.sent()).data;
|
|
@@ -1647,7 +1692,7 @@ var useOTPHandler = function (_a) {
|
|
|
1647
1692
|
idToken,
|
|
1648
1693
|
authenticationType,
|
|
1649
1694
|
onAuthComplete,
|
|
1650
|
-
|
|
1695
|
+
MFAEndpoint,
|
|
1651
1696
|
attemptCount,
|
|
1652
1697
|
isMaxAttemptsReached,
|
|
1653
1698
|
]);
|
|
@@ -1672,33 +1717,54 @@ var MFAOptions = function (_a) {
|
|
|
1672
1717
|
var _d = useState(false), otpVisible = _d[0], setOtpVisible = _d[1];
|
|
1673
1718
|
var _e = useState(false), showSuccessAnimation = _e[0], setShowSuccessAnimation = _e[1];
|
|
1674
1719
|
var _f = useState(null), authType = _f[0], setAuthType = _f[1];
|
|
1720
|
+
var _g = useState(""), lastOTPCode = _g[0], setLastOTPCode = _g[1];
|
|
1675
1721
|
var context = useCAMSContext();
|
|
1676
|
-
var
|
|
1722
|
+
var _h = context.authMode === "MSAL" && "sendEmailOTP" in context
|
|
1677
1723
|
? context
|
|
1678
|
-
: { sendEmailOTP: null }
|
|
1724
|
+
: { sendEmailOTP: null, completeMFA: null }, sendEmailOTP = _h.sendEmailOTP, completeMFA = _h.completeMFA;
|
|
1679
1725
|
var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
|
|
1680
1726
|
var idToken = context.authMode === "MSAL" ? context.idToken : "";
|
|
1681
|
-
var
|
|
1727
|
+
var _j = useOTPHandler({
|
|
1682
1728
|
accessToken: accessToken || "",
|
|
1683
1729
|
idToken: idToken || "",
|
|
1684
1730
|
provider: "MSAL",
|
|
1685
1731
|
appCode: context.appCode || "",
|
|
1686
1732
|
authenticationType: authType,
|
|
1687
|
-
|
|
1688
|
-
onAuthComplete: function (state, data) {
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1733
|
+
MFAEndpoint: MFAEndpoint,
|
|
1734
|
+
onAuthComplete: function (state, data) { return __awaiter(void 0, void 0, void 0, function () {
|
|
1735
|
+
var error_1;
|
|
1736
|
+
return __generator(this, function (_a) {
|
|
1737
|
+
switch (_a.label) {
|
|
1738
|
+
case 0:
|
|
1739
|
+
if (!state) return [3 /*break*/, 5];
|
|
1740
|
+
if (!(completeMFA && authType && lastOTPCode)) return [3 /*break*/, 4];
|
|
1741
|
+
_a.label = 1;
|
|
1742
|
+
case 1:
|
|
1743
|
+
_a.trys.push([1, 3, , 4]);
|
|
1744
|
+
return [4 /*yield*/, completeMFA(lastOTPCode, authType)];
|
|
1745
|
+
case 2:
|
|
1746
|
+
_a.sent();
|
|
1747
|
+
return [3 /*break*/, 4];
|
|
1748
|
+
case 3:
|
|
1749
|
+
error_1 = _a.sent();
|
|
1750
|
+
console.error("Failed to complete MFA:", error_1);
|
|
1751
|
+
return [3 /*break*/, 4];
|
|
1752
|
+
case 4:
|
|
1753
|
+
setShowSuccessAnimation(true);
|
|
1754
|
+
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(ShieldCheck, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: "Multi-Factor Authentication Successful" })] }));
|
|
1755
|
+
setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(true); }, 2000);
|
|
1756
|
+
return [3 /*break*/, 6];
|
|
1757
|
+
case 5:
|
|
1758
|
+
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(ShieldClose, { className: "w-4 h-4" }), jsxRuntimeExports.jsx("span", { children: (data === null || data === void 0 ? void 0 : data.message) || "Invalid code. Please try again." })] }));
|
|
1759
|
+
if (isMaxAttemptsReached) {
|
|
1760
|
+
setTimeout(function () { return onComplete === null || onComplete === void 0 ? void 0 : onComplete(false); }, 1000);
|
|
1761
|
+
}
|
|
1762
|
+
_a.label = 6;
|
|
1763
|
+
case 6: return [2 /*return*/];
|
|
1698
1764
|
}
|
|
1699
|
-
}
|
|
1700
|
-
},
|
|
1701
|
-
}), handleSubmitOTP =
|
|
1765
|
+
});
|
|
1766
|
+
}); },
|
|
1767
|
+
}), handleSubmitOTP = _j.handleSubmitOTP, loading = _j.loading, setLoading = _j.setLoading, attemptCount = _j.attemptCount, remainingAttempts = _j.remainingAttempts, isMaxAttemptsReached = _j.isMaxAttemptsReached, resetAttempts = _j.resetAttempts;
|
|
1702
1768
|
var handleGoBack = function () {
|
|
1703
1769
|
setAuthType(null);
|
|
1704
1770
|
setOtpVisible(false);
|
|
@@ -1707,9 +1773,9 @@ var MFAOptions = function (_a) {
|
|
|
1707
1773
|
};
|
|
1708
1774
|
// Show success animation if authentication is successful
|
|
1709
1775
|
if (showSuccessAnimation) {
|
|
1710
|
-
return (jsxRuntimeExports.jsx(Card, { className: "mx-auto space-y-6 p-6 bg-white rounded-lg shadow-md", children: jsxRuntimeExports.jsx(AuthSuccessAnimation, { onComplete: function () {
|
|
1711
|
-
|
|
1712
|
-
|
|
1776
|
+
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 () {
|
|
1777
|
+
// Animation completed, can add additional logic here if needed
|
|
1778
|
+
} }) }) }));
|
|
1713
1779
|
}
|
|
1714
1780
|
var content = jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
|
|
1715
1781
|
if (!authType) {
|
|
@@ -1745,12 +1811,18 @@ var MFAOptions = function (_a) {
|
|
|
1745
1811
|
setAuthType(null);
|
|
1746
1812
|
setOtpVisible(false);
|
|
1747
1813
|
setValue("");
|
|
1748
|
-
}, 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:
|
|
1814
|
+
}, 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) {
|
|
1815
|
+
setLastOTPCode(code);
|
|
1816
|
+
return handleSubmitOTP(code);
|
|
1817
|
+
}, 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" })] }) })] }));
|
|
1749
1818
|
}
|
|
1750
1819
|
else if (authType === "AuthenticatorCode") {
|
|
1751
|
-
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:
|
|
1820
|
+
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) {
|
|
1821
|
+
setLastOTPCode(code);
|
|
1822
|
+
return handleSubmitOTP(code);
|
|
1823
|
+
}, fieldName: "AuthenticatorCode", attemptCount: attemptCount, remainingAttempts: remainingAttempts, isMaxAttemptsReached: isMaxAttemptsReached })] })) })] }));
|
|
1752
1824
|
}
|
|
1753
|
-
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(ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
|
|
1825
|
+
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(ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
|
|
1754
1826
|
};
|
|
1755
1827
|
|
|
1756
1828
|
var LoginButton = function () {
|