@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
|
@@ -14,7 +14,6 @@ interface MSALProviderProps extends BaseProviderProps, UseCAMSMSALAuthOptions {
|
|
|
14
14
|
mode: "MSAL";
|
|
15
15
|
msalConfig: Configuration;
|
|
16
16
|
msalInstance?: PublicClientApplication;
|
|
17
|
-
validateTokenUrl?: string;
|
|
18
17
|
}
|
|
19
18
|
type UnifiedCAMSProviderProps = RegularProviderProps | MSALProviderProps;
|
|
20
19
|
export declare function UnifiedCAMSProvider(props: UnifiedCAMSProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,7 +6,6 @@ interface BaseCAMSContextValue {
|
|
|
6
6
|
userProfile: Profile | null;
|
|
7
7
|
setUserProfile: (profile: Profile | null) => void;
|
|
8
8
|
authMode: AuthMode;
|
|
9
|
-
validateTokenUrl?: string;
|
|
10
9
|
}
|
|
11
10
|
interface RegularCAMSContextValue extends BaseCAMSContextValue, UseCAMSAuthReturn {
|
|
12
11
|
authMode: "REGULAR";
|
|
@@ -5,12 +5,11 @@ export interface UseCAMSMSALAuthOptions {
|
|
|
5
5
|
onTokenExpired?: () => void;
|
|
6
6
|
scopes?: string[];
|
|
7
7
|
storageKey?: string;
|
|
8
|
-
mfaUrl?: string;
|
|
9
8
|
prompt?: string;
|
|
10
9
|
messageOrigin?: string;
|
|
11
10
|
appCode: string;
|
|
12
11
|
allowedOrigins?: string[];
|
|
13
|
-
|
|
12
|
+
MFAEndpoint: string;
|
|
14
13
|
}
|
|
15
14
|
export interface UseCAMSMSALAuthReturn {
|
|
16
15
|
login: () => Promise<void>;
|
package/dist/index.cjs.js
CHANGED
|
@@ -260,7 +260,7 @@ function useCAMSMSALAuth(options) {
|
|
|
260
260
|
var _this = this;
|
|
261
261
|
if (options === void 0) { options = {
|
|
262
262
|
appCode: "",
|
|
263
|
-
|
|
263
|
+
MFAEndpoint: "/auth/multi-factor",
|
|
264
264
|
storageKey: "CAMS-MSAL-AUTH-SDK",
|
|
265
265
|
}; }
|
|
266
266
|
var _a = msalReact.useMsal(), instance = _a.instance, inProgress = _a.inProgress, accounts = _a.accounts;
|
|
@@ -330,74 +330,67 @@ function useCAMSMSALAuth(options) {
|
|
|
330
330
|
// handleRedirect();
|
|
331
331
|
// }, []);
|
|
332
332
|
var login = React.useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
333
|
-
var err_1, camsError_1, camsError;
|
|
334
|
-
var _a, _b, _c;
|
|
335
|
-
return __generator(this, function (
|
|
336
|
-
switch (
|
|
333
|
+
var response, mfaConfig, authenticator, err_1, camsError_1, camsError;
|
|
334
|
+
var _a, _b, _c, _d;
|
|
335
|
+
return __generator(this, function (_e) {
|
|
336
|
+
switch (_e.label) {
|
|
337
337
|
case 0:
|
|
338
338
|
setError(null);
|
|
339
|
-
|
|
339
|
+
_e.label = 1;
|
|
340
340
|
case 1:
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
// scopes,
|
|
344
|
-
// prompt: options.prompt || "login",
|
|
345
|
-
// });
|
|
346
|
-
return [4 /*yield*/, instance
|
|
347
|
-
.loginPopup({
|
|
341
|
+
_e.trys.push([1, 3, , 4]);
|
|
342
|
+
return [4 /*yield*/, instance.loginPopup({
|
|
348
343
|
scopes: scopes,
|
|
349
344
|
prompt: options.prompt || "login",
|
|
350
|
-
})
|
|
351
|
-
.then(function (response) {
|
|
352
|
-
var _a;
|
|
353
|
-
camsSdk.Logger.debug("Login Token response:", {
|
|
354
|
-
accessToken: response.accessToken,
|
|
355
|
-
idToken: response.idToken,
|
|
356
|
-
});
|
|
357
|
-
setAccessToken(response.accessToken);
|
|
358
|
-
setIdToken(response.idToken);
|
|
359
|
-
// Initialize MFA authenticator
|
|
360
|
-
var mfaConfig = {
|
|
361
|
-
accessToken: response.accessToken,
|
|
362
|
-
idToken: response.idToken,
|
|
363
|
-
appCode: options.appCode,
|
|
364
|
-
provider: "MSAL",
|
|
365
|
-
apiEndpoint: options.mfaApiEndpoint,
|
|
366
|
-
};
|
|
367
|
-
var authenticator = new camsSdk.CAMSMFAAuthenticator(mfaConfig);
|
|
368
|
-
setMfaAuthenticator(authenticator);
|
|
369
|
-
setRequiresMFA(true);
|
|
370
|
-
// Don't persist as authenticated until MFA is complete
|
|
371
|
-
if (typeof window !== "undefined") {
|
|
372
|
-
localStorage.setItem(options.storageKey, JSON.stringify({
|
|
373
|
-
isAuthenticated: false,
|
|
374
|
-
requiresMFA: true,
|
|
375
|
-
accessToken: response.accessToken,
|
|
376
|
-
idToken: response.idToken,
|
|
377
|
-
}));
|
|
378
|
-
}
|
|
379
|
-
(_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
|
|
380
345
|
})];
|
|
381
346
|
case 2:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
347
|
+
response = _e.sent();
|
|
348
|
+
camsSdk.Logger.debug("Login Token response:", {
|
|
349
|
+
accessToken: response.accessToken,
|
|
350
|
+
idToken: response.idToken,
|
|
351
|
+
});
|
|
352
|
+
setAccessToken(response.accessToken);
|
|
353
|
+
setIdToken(response.idToken);
|
|
354
|
+
mfaConfig = {
|
|
355
|
+
accessToken: response.accessToken,
|
|
356
|
+
idToken: response.idToken,
|
|
357
|
+
appCode: options.appCode,
|
|
358
|
+
provider: "MSAL",
|
|
359
|
+
apiEndpoint: options.MFAEndpoint,
|
|
360
|
+
};
|
|
361
|
+
authenticator = new camsSdk.CAMSMFAAuthenticator(mfaConfig);
|
|
362
|
+
setMfaAuthenticator(authenticator);
|
|
363
|
+
setRequiresMFA(true);
|
|
364
|
+
// Don't persist as authenticated until MFA is complete
|
|
365
|
+
if (typeof window !== "undefined") {
|
|
366
|
+
localStorage.setItem(options.storageKey, JSON.stringify({
|
|
367
|
+
isAuthenticated: false,
|
|
368
|
+
requiresMFA: true,
|
|
369
|
+
accessToken: response.accessToken,
|
|
370
|
+
idToken: response.idToken,
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
(_a = options.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(options, response.accessToken);
|
|
387
374
|
return [3 /*break*/, 4];
|
|
388
375
|
case 3:
|
|
389
|
-
err_1 =
|
|
376
|
+
err_1 = _e.sent();
|
|
377
|
+
// Handle user cancellation gracefully
|
|
378
|
+
if (err_1.errorCode === "user_cancelled") {
|
|
379
|
+
camsSdk.Logger.info("User cancelled login");
|
|
380
|
+
setError(null); // Don't treat cancellation as an error
|
|
381
|
+
return [2 /*return*/];
|
|
382
|
+
}
|
|
390
383
|
// If popup is blocked
|
|
391
384
|
if (err_1.errorCode === "popup_window_error" ||
|
|
392
|
-
((
|
|
393
|
-
camsError_1 = new camsSdk.CAMSError(camsSdk.CAMSErrorType.POPUP_BLOCKED, "
|
|
385
|
+
((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.includes("popup"))) {
|
|
386
|
+
camsError_1 = new camsSdk.CAMSError(camsSdk.CAMSErrorType.POPUP_BLOCKED, "Popup blocked by browser. Please allow popups and try again.");
|
|
394
387
|
setError(camsError_1);
|
|
395
|
-
(
|
|
388
|
+
(_c = options.onAuthError) === null || _c === void 0 ? void 0 : _c.call(options, camsError_1);
|
|
396
389
|
return [2 /*return*/];
|
|
397
390
|
}
|
|
398
|
-
camsError = new camsSdk.CAMSError(camsSdk.CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1);
|
|
391
|
+
camsError = new camsSdk.CAMSError(camsSdk.CAMSErrorType.API_VALIDATION_ERROR, "Login failed: " + err_1.message || err_1);
|
|
399
392
|
setError(camsError);
|
|
400
|
-
(
|
|
393
|
+
(_d = options.onAuthError) === null || _d === void 0 ? void 0 : _d.call(options, camsError);
|
|
401
394
|
return [3 /*break*/, 4];
|
|
402
395
|
case 4: return [2 /*return*/];
|
|
403
396
|
}
|
|
@@ -1145,14 +1138,14 @@ var deleteCookie = function (name) {
|
|
|
1145
1138
|
};
|
|
1146
1139
|
function CAMSProviderCore(props) {
|
|
1147
1140
|
var _this = this;
|
|
1148
|
-
var
|
|
1141
|
+
var children = props.children, mode = props.mode, appCode = props.appCode;
|
|
1149
1142
|
// Always call both hooks to satisfy Rules of Hooks
|
|
1150
1143
|
var regularAuth = useCAMSAuth(mode === "REGULAR"
|
|
1151
1144
|
? __assign(__assign({}, props), { appCode: appCode })
|
|
1152
1145
|
: { appCode: "" });
|
|
1153
1146
|
var msalAuth = useCAMSMSALAuth(mode === "MSAL"
|
|
1154
1147
|
? __assign(__assign({}, props), { appCode: appCode })
|
|
1155
|
-
: { appCode: "" });
|
|
1148
|
+
: { appCode: "", MFAEndpoint: "/auth/multi-factor" });
|
|
1156
1149
|
var auth = mode === "REGULAR" ? regularAuth : msalAuth;
|
|
1157
1150
|
var profileStorageKey = "".concat(auth.storageKey, "-PROFILE");
|
|
1158
1151
|
var getInitialProfile = function () {
|
|
@@ -1166,7 +1159,7 @@ function CAMSProviderCore(props) {
|
|
|
1166
1159
|
return null;
|
|
1167
1160
|
}
|
|
1168
1161
|
};
|
|
1169
|
-
var
|
|
1162
|
+
var _a = React.useState(getInitialProfile), userProfile = _a[0], setUserProfile = _a[1];
|
|
1170
1163
|
React.useEffect(function () {
|
|
1171
1164
|
if (typeof window !== "undefined") {
|
|
1172
1165
|
var storedProfile = getCookie(profileStorageKey);
|
|
@@ -1204,7 +1197,11 @@ function CAMSProviderCore(props) {
|
|
|
1204
1197
|
}); };
|
|
1205
1198
|
// Handle MFA completion for MSAL mode
|
|
1206
1199
|
React.useEffect(function () {
|
|
1207
|
-
if (mode === "MSAL" &&
|
|
1200
|
+
if (mode === "MSAL" &&
|
|
1201
|
+
"requiresMFA" in auth &&
|
|
1202
|
+
!auth.requiresMFA &&
|
|
1203
|
+
auth.isAuthenticated &&
|
|
1204
|
+
!userProfile) {
|
|
1208
1205
|
// MFA completed, extract profile from stored data
|
|
1209
1206
|
var storedData = getCookie(auth.storageKey);
|
|
1210
1207
|
if (storedData) {
|
|
@@ -1219,8 +1216,8 @@ function CAMSProviderCore(props) {
|
|
|
1219
1216
|
}
|
|
1220
1217
|
}, [mode, auth, userProfile]);
|
|
1221
1218
|
var value = React.useMemo(function () {
|
|
1222
|
-
return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode
|
|
1223
|
-
}, [auth, userProfile, mode
|
|
1219
|
+
return (__assign(__assign({}, auth), { logout: enhancedLogout, userProfile: userProfile, setUserProfile: setUserProfile, authMode: mode }));
|
|
1220
|
+
}, [auth, userProfile, mode]);
|
|
1224
1221
|
return jsxRuntimeExports.jsx(CAMSContext.Provider, { value: value, children: children });
|
|
1225
1222
|
}
|
|
1226
1223
|
function UnifiedCAMSProvider(props) {
|
|
@@ -1229,11 +1226,11 @@ function UnifiedCAMSProvider(props) {
|
|
|
1229
1226
|
if (!appCodeValidation.success) {
|
|
1230
1227
|
throw new Error("Invalid appCode: ".concat(appCodeValidation.error.issues[0].message));
|
|
1231
1228
|
}
|
|
1232
|
-
// Validate
|
|
1233
|
-
if (props.mode === "MSAL" && props.
|
|
1234
|
-
var urlValidation = UrlSchema.safeParse(props.
|
|
1229
|
+
// Validate apiEndpoint if provided
|
|
1230
|
+
if (props.mode === "MSAL" && props.MFAEndpoint) {
|
|
1231
|
+
var urlValidation = UrlSchema.safeParse(props.MFAEndpoint);
|
|
1235
1232
|
if (!urlValidation.success) {
|
|
1236
|
-
throw new Error("Invalid
|
|
1233
|
+
throw new Error("Invalid apiEndpoint: ".concat(urlValidation.error.issues[0].message));
|
|
1237
1234
|
}
|
|
1238
1235
|
}
|
|
1239
1236
|
if (props.mode === "MSAL") {
|
|
@@ -1687,18 +1684,18 @@ var MFAOptions = function (_a) {
|
|
|
1687
1684
|
var _f = React.useState(null), authType = _f[0], setAuthType = _f[1];
|
|
1688
1685
|
var context = useCAMSContext();
|
|
1689
1686
|
var isSDKMode = context.authMode === "MSAL" && "completeMFA" in context;
|
|
1690
|
-
var
|
|
1687
|
+
var sendEmailOTP = (isSDKMode
|
|
1691
1688
|
? context
|
|
1692
|
-
: {
|
|
1689
|
+
: { sendEmailOTP: null }).sendEmailOTP;
|
|
1693
1690
|
var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
|
|
1694
1691
|
var idToken = context.authMode === "MSAL" ? context.idToken : "";
|
|
1695
|
-
var
|
|
1692
|
+
var _g = useOTPHandler({
|
|
1696
1693
|
provider: "azure",
|
|
1697
1694
|
accessToken: accessToken || "",
|
|
1698
1695
|
idToken: idToken || "",
|
|
1699
1696
|
appCode: context.appCode || "",
|
|
1700
1697
|
authenticationType: authType,
|
|
1701
|
-
validateTokenUrl: context.
|
|
1698
|
+
validateTokenUrl: ((context.authMode === "MSAL" && "MFAEndpoint" in context) ? (context.MFAEndpoint || "/api/auth/verify-mfa") : "/api/validate-token"),
|
|
1702
1699
|
onAuthComplete: function (success, data) {
|
|
1703
1700
|
if (success) {
|
|
1704
1701
|
setShowSuccessAnimation(true);
|
|
@@ -1712,7 +1709,7 @@ var MFAOptions = function (_a) {
|
|
|
1712
1709
|
}
|
|
1713
1710
|
}
|
|
1714
1711
|
},
|
|
1715
|
-
}), handleSubmitOTP =
|
|
1712
|
+
}), handleSubmitOTP = _g.handleSubmitOTP, loading = _g.loading, attemptCount = _g.attemptCount, isMaxAttemptsReached = _g.isMaxAttemptsReached, remainingAttempts = _g.remainingAttempts, resetAttempts = _g.resetAttempts;
|
|
1716
1713
|
var handleGoBack = function () {
|
|
1717
1714
|
setAuthType(null);
|
|
1718
1715
|
setOtpVisible(false);
|
|
@@ -1750,7 +1747,7 @@ var MFAOptions = function (_a) {
|
|
|
1750
1747
|
resetAttempts();
|
|
1751
1748
|
setAuthType("AuthenticatorCode");
|
|
1752
1749
|
setOtpVisible(true);
|
|
1753
|
-
}, 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" })] })] })] })] }));
|
|
1750
|
+
}, 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" })] })] })] })] }));
|
|
1754
1751
|
}
|
|
1755
1752
|
else if (authType === "EmailOTP") {
|
|
1756
1753
|
content = (jsxRuntimeExports.jsxs(Dialog, { open: otpVisible, onOpenChange: function () {
|
|
@@ -1762,7 +1759,7 @@ var MFAOptions = function (_a) {
|
|
|
1762
1759
|
else if (authType === "AuthenticatorCode") {
|
|
1763
1760
|
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 })] })) })] }));
|
|
1764
1761
|
}
|
|
1765
|
-
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: "/
|
|
1762
|
+
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(lucideReact.ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }));
|
|
1766
1763
|
};
|
|
1767
1764
|
|
|
1768
1765
|
var LoginButton = function () {
|