@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.
@@ -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
- mfaApiEndpoint?: string;
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
- mfaUrl: "/auth/multi-factor",
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 (_d) {
336
- switch (_d.label) {
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
- _d.label = 1;
339
+ _e.label = 1;
340
340
  case 1:
341
- _d.trys.push([1, 3, , 4]);
342
- // await instance.loginR edirect({
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
- // await instance.loginR edirect({
383
- // scopes,
384
- // prompt: options.prompt || "login",
385
- // });
386
- _d.sent();
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 = _d.sent();
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
- ((_a = err_1.message) === null || _a === void 0 ? void 0 : _a.includes("popup"))) {
393
- camsError_1 = new camsSdk.CAMSError(camsSdk.CAMSErrorType.POPUP_BLOCKED, "Both popup and redirect failed: " + err_1);
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
- (_b = options.onAuthError) === null || _b === void 0 ? void 0 : _b.call(options, camsError_1);
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
- (_c = options.onAuthError) === null || _c === void 0 ? void 0 : _c.call(options, camsError);
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 _a = props, children = _a.children, mode = _a.mode, appCode = _a.appCode, validateTokenUrl = _a.validateTokenUrl;
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 _b = React.useState(getInitialProfile), userProfile = _b[0], setUserProfile = _b[1];
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" && "requiresMFA" in auth && !auth.requiresMFA && auth.isAuthenticated && !userProfile) {
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, validateTokenUrl: validateTokenUrl }));
1223
- }, [auth, userProfile, mode, validateTokenUrl]);
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 validateTokenUrl if provided
1233
- if (props.mode === "MSAL" && props.validateTokenUrl) {
1234
- var urlValidation = UrlSchema.safeParse(props.validateTokenUrl);
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 validateTokenUrl: ".concat(urlValidation.error.issues[0].message));
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 _g = isSDKMode
1687
+ var sendEmailOTP = (isSDKMode
1691
1688
  ? context
1692
- : { completeMFA: null, sendEmailOTP: null }; _g.completeMFA; var sendEmailOTP = _g.sendEmailOTP;
1689
+ : { sendEmailOTP: null }).sendEmailOTP;
1693
1690
  var accessToken = context.authMode === "MSAL" ? context.accessToken : "";
1694
1691
  var idToken = context.authMode === "MSAL" ? context.idToken : "";
1695
- var _h = useOTPHandler({
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.validateTokenUrl || "/api/validate-token",
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 = _h.handleSubmitOTP, loading = _h.loading, attemptCount = _h.attemptCount, isMaxAttemptsReached = _h.isMaxAttemptsReached, remainingAttempts = _h.remainingAttempts, resetAttempts = _h.resetAttempts;
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: "/OTPAuthentication1.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" })] })] }));
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 () {