@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/OTPAuthentication.svg +1 -0
- package/dist/components/UnifiedCAMSProvider.d.ts +0 -1
- package/dist/context/CAMSContext.d.ts +0 -1
- package/dist/hooks/useCAMSMSALAuth.d.ts +1 -2
- package/dist/index.cjs.js +50 -24
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +51 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/microsoftauthenticator.svg +18 -0
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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" &&
|
|
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
|
|
1196
|
-
}, [auth, userProfile, mode
|
|
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
|
|
1206
|
-
if (props.mode === "MSAL" && props.
|
|
1207
|
-
var urlValidation = UrlSchema.safeParse(props.
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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.
|
|
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 =
|
|
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:
|
|
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:
|
|
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 () {
|