@nibssplc/cams-sdk-react 0.0.1-beta.59 → 0.0.1-beta.61
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/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 +68 -71
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +69 -72
- package/dist/index.esm.js.map +1 -1
- 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, CAMSError, CAMSErrorType,
|
|
3
|
+
import { isPopupWindow, initializePopupAuth, CAMSSessionManager, Logger, CAMSError, CAMSErrorType, CAMSMFAAuthenticator } 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;
|
|
@@ -310,74 +310,67 @@ function useCAMSMSALAuth(options) {
|
|
|
310
310
|
// handleRedirect();
|
|
311
311
|
// }, []);
|
|
312
312
|
var login = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
313
|
-
var err_1, camsError_1, camsError;
|
|
314
|
-
var _a, _b, _c;
|
|
315
|
-
return __generator(this, function (
|
|
316
|
-
switch (
|
|
313
|
+
var response, mfaConfig, authenticator, err_1, camsError_1, camsError;
|
|
314
|
+
var _a, _b, _c, _d;
|
|
315
|
+
return __generator(this, function (_e) {
|
|
316
|
+
switch (_e.label) {
|
|
317
317
|
case 0:
|
|
318
318
|
setError(null);
|
|
319
|
-
|
|
319
|
+
_e.label = 1;
|
|
320
320
|
case 1:
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// scopes,
|
|
324
|
-
// prompt: options.prompt || "login",
|
|
325
|
-
// });
|
|
326
|
-
return [4 /*yield*/, instance
|
|
327
|
-
.loginPopup({
|
|
321
|
+
_e.trys.push([1, 3, , 4]);
|
|
322
|
+
return [4 /*yield*/, instance.loginPopup({
|
|
328
323
|
scopes: scopes,
|
|
329
324
|
prompt: options.prompt || "login",
|
|
330
|
-
})
|
|
331
|
-
.then(function (response) {
|
|
332
|
-
var _a;
|
|
333
|
-
Logger.debug("Login Token response:", {
|
|
334
|
-
accessToken: response.accessToken,
|
|
335
|
-
idToken: response.idToken,
|
|
336
|
-
});
|
|
337
|
-
setAccessToken(response.accessToken);
|
|
338
|
-
setIdToken(response.idToken);
|
|
339
|
-
// Initialize MFA authenticator
|
|
340
|
-
var mfaConfig = {
|
|
341
|
-
accessToken: response.accessToken,
|
|
342
|
-
idToken: response.idToken,
|
|
343
|
-
appCode: options.appCode,
|
|
344
|
-
provider: "MSAL",
|
|
345
|
-
apiEndpoint: options.mfaApiEndpoint,
|
|
346
|
-
};
|
|
347
|
-
var authenticator = new CAMSMFAAuthenticator(mfaConfig);
|
|
348
|
-
setMfaAuthenticator(authenticator);
|
|
349
|
-
setRequiresMFA(true);
|
|
350
|
-
// Don't persist as authenticated until MFA is complete
|
|
351
|
-
if (typeof window !== "undefined") {
|
|
352
|
-
localStorage.setItem(options.storageKey, JSON.stringify({
|
|
353
|
-
isAuthenticated: false,
|
|
354
|
-
requiresMFA: true,
|
|
355
|
-
accessToken: response.accessToken,
|
|
356
|
-
idToken: response.idToken,
|
|
357
|
-
}));
|
|
358
|
-
}
|
|
359
|
-
(_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
|
|
360
325
|
})];
|
|
361
326
|
case 2:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
327
|
+
response = _e.sent();
|
|
328
|
+
Logger.debug("Login Token response:", {
|
|
329
|
+
accessToken: response.accessToken,
|
|
330
|
+
idToken: response.idToken,
|
|
331
|
+
});
|
|
332
|
+
setAccessToken(response.accessToken);
|
|
333
|
+
setIdToken(response.idToken);
|
|
334
|
+
mfaConfig = {
|
|
335
|
+
accessToken: response.accessToken,
|
|
336
|
+
idToken: response.idToken,
|
|
337
|
+
appCode: options.appCode,
|
|
338
|
+
provider: "MSAL",
|
|
339
|
+
apiEndpoint: options.MFAEndpoint,
|
|
340
|
+
};
|
|
341
|
+
authenticator = new CAMSMFAAuthenticator(mfaConfig);
|
|
342
|
+
setMfaAuthenticator(authenticator);
|
|
343
|
+
setRequiresMFA(true);
|
|
344
|
+
// Don't persist as authenticated until MFA is complete
|
|
345
|
+
if (typeof window !== "undefined") {
|
|
346
|
+
localStorage.setItem(options.storageKey, JSON.stringify({
|
|
347
|
+
isAuthenticated: false,
|
|
348
|
+
requiresMFA: true,
|
|
349
|
+
accessToken: response.accessToken,
|
|
350
|
+
idToken: response.idToken,
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
(_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
|
|
367
354
|
return [3 /*break*/, 4];
|
|
368
355
|
case 3:
|
|
369
|
-
err_1 =
|
|
356
|
+
err_1 = _e.sent();
|
|
357
|
+
// Handle user cancellation gracefully
|
|
358
|
+
if (err_1.errorCode === "user_cancelled") {
|
|
359
|
+
Logger.info("User cancelled login");
|
|
360
|
+
setError(null); // Don't treat cancellation as an error
|
|
361
|
+
return [2 /*return*/];
|
|
362
|
+
}
|
|
370
363
|
// If popup is blocked
|
|
371
364
|
if (err_1.errorCode === "popup_window_error" ||
|
|
372
|
-
((
|
|
373
|
-
camsError_1 = new CAMSError(CAMSErrorType.POPUP_BLOCKED, "
|
|
365
|
+
((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.includes("popup"))) {
|
|
366
|
+
camsError_1 = new CAMSError(CAMSErrorType.POPUP_BLOCKED, "Popup blocked by browser. Please allow popups and try again.");
|
|
374
367
|
setError(camsError_1);
|
|
375
|
-
(
|
|
368
|
+
(_c = options.onAuthError) === null || _c === void 0 ? void 0 : _c.call(options, camsError_1);
|
|
376
369
|
return [2 /*return*/];
|
|
377
370
|
}
|
|
378
|
-
camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1);
|
|
371
|
+
camsError = new CAMSError(CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1.message || err_1);
|
|
379
372
|
setError(camsError);
|
|
380
|
-
(
|
|
373
|
+
(_d = options.onAuthError) === null || _d === void 0 ? void 0 : _d.call(options, camsError);
|
|
381
374
|
return [3 /*break*/, 4];
|
|
382
375
|
case 4: return [2 /*return*/];
|
|
383
376
|
}
|
|
@@ -1125,14 +1118,14 @@ var deleteCookie = function (name) {
|
|
|
1125
1118
|
};
|
|
1126
1119
|
function CAMSProviderCore(props) {
|
|
1127
1120
|
var _this = this;
|
|
1128
|
-
var
|
|
1121
|
+
var children = props.children, mode = props.mode, appCode = props.appCode;
|
|
1129
1122
|
// Always call both hooks to satisfy Rules of Hooks
|
|
1130
1123
|
var regularAuth = useCAMSAuth(mode === "REGULAR"
|
|
1131
1124
|
? __assign(__assign({}, props), { appCode: appCode })
|
|
1132
1125
|
: { appCode: "" });
|
|
1133
1126
|
var msalAuth = useCAMSMSALAuth(mode === "MSAL"
|
|
1134
1127
|
? __assign(__assign({}, props), { appCode: appCode })
|
|
1135
|
-
: { appCode: "" });
|
|
1128
|
+
: { appCode: "", MFAEndpoint: "/auth/multi-factor" });
|
|
1136
1129
|
var auth = mode === "REGULAR" ? regularAuth : msalAuth;
|
|
1137
1130
|
var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
|
|
1138
1131
|
var getInitialProfile = function () {
|
|
@@ -1146,7 +1139,7 @@ function CAMSProviderCore(props) {
|
|
|
1146
1139
|
return null;
|
|
1147
1140
|
}
|
|
1148
1141
|
};
|
|
1149
|
-
var
|
|
1142
|
+
var _a = useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
|
|
1150
1143
|
useEffect(function () {
|
|
1151
1144
|
if (typeof window !== "undefined") {
|
|
1152
1145
|
var storedProfile = getCookie(profileStorageKey);
|
|
@@ -1184,7 +1177,11 @@ function CAMSProviderCore(props) {
|
|
|
1184
1177
|
}); };
|
|
1185
1178
|
// Handle MFA completion for MSAL mode
|
|
1186
1179
|
useEffect(function () {
|
|
1187
|
-
if (mode === "MSAL" &&
|
|
1180
|
+
if (mode === "MSAL" &&
|
|
1181
|
+
"requiresMFA" in auth &&
|
|
1182
|
+
!auth.requiresMFA &&
|
|
1183
|
+
auth.isAuthenticated &&
|
|
1184
|
+
!userProfile) {
|
|
1188
1185
|
// MFA completed, extract profile from stored data
|
|
1189
1186
|
var storedData = getCookie(auth.storageKey);
|
|
1190
1187
|
if (storedData) {
|
|
@@ -1199,8 +1196,8 @@ function CAMSProviderCore(props) {
|
|
|
1199
1196
|
}
|
|
1200
1197
|
}, [mode, auth, userProfile]);
|
|
1201
1198
|
var value = useMemo(function () {
|
|
1202
|
-
return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode
|
|
1203
|
-
}, [auth, userProfile, mode
|
|
1199
|
+
return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
|
|
1200
|
+
}, [auth, userProfile, mode]);
|
|
1204
1201
|
return jsxRuntimeExports.jsx(CAMSContext.Provider, { value: value, children: children });
|
|
1205
1202
|
}
|
|
1206
1203
|
function UnifiedCAMSProvider(props) {
|
|
@@ -1209,11 +1206,11 @@ function UnifiedCAMSProvider(props) {
|
|
|
1209
1206
|
if (!appCodeValidation.success) {
|
|
1210
1207
|
throw new Error("Invalid appCode: ".concat(appCodeValidation.error.issues[0].message));
|
|
1211
1208
|
}
|
|
1212
|
-
// Validate
|
|
1213
|
-
if (props.mode === "MSAL" && props.
|
|
1214
|
-
var urlValidation = UrlSchema.safeParse(props.
|
|
1209
|
+
// Validate apiEndpoint if provided
|
|
1210
|
+
if (props.mode === "MSAL" && props.MFAEndpoint) {
|
|
1211
|
+
var urlValidation = UrlSchema.safeParse(props.MFAEndpoint);
|
|
1215
1212
|
if (!urlValidation.success) {
|
|
1216
|
-
throw new Error("Invalid
|
|
1213
|
+
throw new Error("Invalid apiEndpoint: ".concat(urlValidation.error.issues[0].message));
|
|
1217
1214
|
}
|
|
1218
1215
|
}
|
|
1219
1216
|
if (props.mode === "MSAL") {
|
|
@@ -1667,18 +1664,18 @@ var MFAOptions = function (_a) {
|
|
|
1667
1664
|
var _f = useState(null), authType = _f[0], setAuthType = _f[1];
|
|
1668
1665
|
var context = useCAMSContext();
|
|
1669
1666
|
var isSDKMode = context.authMode === "MSAL" && "completeMFA" in context;
|
|
1670
|
-
var
|
|
1667
|
+
var sendEmailOTP = (isSDKMode
|
|
1671
1668
|
? context
|
|
1672
|
-
: {
|
|
1669
|
+
: { sendEmailOTP: null }).sendEmailOTP;
|
|
1673
1670
|
var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
|
|
1674
1671
|
var idToken = context.authMode === "MSAL" ? context.idToken : "";
|
|
1675
|
-
var
|
|
1672
|
+
var _g = useOTPHandler({
|
|
1676
1673
|
provider: "azure",
|
|
1677
1674
|
accessToken: accessToken || "",
|
|
1678
1675
|
idToken: idToken || "",
|
|
1679
1676
|
appCode: context.appCode || "",
|
|
1680
1677
|
authenticationType: authType,
|
|
1681
|
-
validateTokenUrl: context.
|
|
1678
|
+
validateTokenUrl: ((context.authMode === "MSAL" && "MFAEndpoint" in context) ? (context.MFAEndpoint || "/api/auth/verify-mfa") : "/api/validate-token"),
|
|
1682
1679
|
onAuthComplete: function (success, data) {
|
|
1683
1680
|
if (success) {
|
|
1684
1681
|
setShowSuccessAnimation(true);
|
|
@@ -1692,7 +1689,7 @@ var MFAOptions = function (_a) {
|
|
|
1692
1689
|
}
|
|
1693
1690
|
}
|
|
1694
1691
|
},
|
|
1695
|
-
}), handleSubmitOTP =
|
|
1692
|
+
}), handleSubmitOTP = _g.handleSubmitOTP, loading = _g.loading, attemptCount = _g.attemptCount, isMaxAttemptsReached = _g.isMaxAttemptsReached, remainingAttempts = _g.remainingAttempts, resetAttempts = _g.resetAttempts;
|
|
1696
1693
|
var handleGoBack = function () {
|
|
1697
1694
|
setAuthType(null);
|
|
1698
1695
|
setOtpVisible(false);
|
|
@@ -1730,7 +1727,7 @@ var MFAOptions = function (_a) {
|
|
|
1730
1727
|
resetAttempts();
|
|
1731
1728
|
setAuthType("AuthenticatorCode");
|
|
1732
1729
|
setOtpVisible(true);
|
|
1733
|
-
}, 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" })] })] })] })] }));
|
|
1730
|
+
}, children: [jsxRuntimeExports.jsx("img", { src: "/images/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" })] })] })] })] }));
|
|
1734
1731
|
}
|
|
1735
1732
|
else if (authType === "EmailOTP") {
|
|
1736
1733
|
content = (jsxRuntimeExports.jsxs(Dialog, { open: otpVisible, onOpenChange: function () {
|
|
@@ -1742,7 +1739,7 @@ var MFAOptions = function (_a) {
|
|
|
1742
1739
|
else if (authType === "AuthenticatorCode") {
|
|
1743
1740
|
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 })] })) })] }));
|
|
1744
1741
|
}
|
|
1745
|
-
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: "/
|
|
1742
|
+
return (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center", 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: "/images/OTPAuthentication.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" })] })] }) }));
|
|
1746
1743
|
};
|
|
1747
1744
|
|
|
1748
1745
|
var LoginButton = function () {
|