@nibssplc/cams-sdk-react 0.0.1-beta.58 → 0.0.1-beta.60

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.
@@ -2,5 +2,5 @@ interface ClientOnlyProps {
2
2
  children: React.ReactNode;
3
3
  fallback?: React.ReactNode;
4
4
  }
5
- export declare function ClientOnly({ children, fallback }: ClientOnlyProps): import("react/jsx-runtime").JSX.Element;
6
- export {};
5
+ declare const ClientOnly: ({ children, fallback }: ClientOnlyProps) => import("react/jsx-runtime").JSX.Element;
6
+ export default ClientOnly;
@@ -0,0 +1,2 @@
1
+ declare const LoginButton: () => import("react/jsx-runtime").JSX.Element;
2
+ export default LoginButton;
@@ -1,6 +1,7 @@
1
1
  interface MFAGateProps {
2
2
  children: React.ReactNode;
3
3
  fallback?: React.ReactNode;
4
+ loginComponent?: React.ComponentType;
4
5
  }
5
- declare const MFAGate: ({ children, fallback }: MFAGateProps) => string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
6
+ declare const MFAGate: ({ children, fallback, loginComponent: LoginComponent }: MFAGateProps) => string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
6
7
  export default MFAGate;
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { PublicClientApplication, Configuration } from "@azure/msal-browser";
3
3
  import { UseCAMSAuthOptions } from "../hooks/useCAMSAuth";
4
4
  import { UseCAMSMSALAuthOptions } from "../hooks/useCAMSMSALAuth";
5
+ import { useCAMSContext } from "../context/CAMSContext";
5
6
  interface BaseProviderProps {
6
7
  children: React.ReactNode;
7
8
  appCode: string;
@@ -19,4 +20,4 @@ type UnifiedCAMSProviderProps = RegularProviderProps | MSALProviderProps;
19
20
  export declare function UnifiedCAMSProvider(props: UnifiedCAMSProviderProps): import("react/jsx-runtime").JSX.Element;
20
21
  export declare const CAMSProvider: (props: Omit<RegularProviderProps, "mode">) => import("react/jsx-runtime").JSX.Element;
21
22
  export declare const CAMSMSALProvider: (props: Omit<MSALProviderProps, "mode">) => import("react/jsx-runtime").JSX.Element;
22
- export {};
23
+ export { useCAMSContext };
package/dist/index.cjs.js CHANGED
@@ -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.mfaApiEndpoint,
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
  }
@@ -1102,7 +1095,7 @@ function useCAMSMSALContext() {
1102
1095
  return context;
1103
1096
  }
1104
1097
 
1105
- function ClientOnly(_a) {
1098
+ var ClientOnly = function (_a) {
1106
1099
  var children = _a.children, _b = _a.fallback, fallback = _b === void 0 ? null : _b;
1107
1100
  var _c = React.useState(false), hasMounted = _c[0], setHasMounted = _c[1];
1108
1101
  React.useEffect(function () {
@@ -1112,7 +1105,7 @@ function ClientOnly(_a) {
1112
1105
  return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: fallback });
1113
1106
  }
1114
1107
  return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
1115
- }
1108
+ };
1116
1109
 
1117
1110
  var CAMSContext = React.createContext(null);
1118
1111
  function useCAMSContext() {
@@ -1143,7 +1136,7 @@ var getCookie = function (name) {
1143
1136
  var deleteCookie = function (name) {
1144
1137
  document.cookie = name + "=; Max-Age=-99999999; path=/";
1145
1138
  };
1146
- function CAMSProviderInner(props) {
1139
+ function CAMSProviderCore(props) {
1147
1140
  var _this = this;
1148
1141
  var _a = props, children = _a.children, mode = _a.mode, appCode = _a.appCode, validateTokenUrl = _a.validateTokenUrl;
1149
1142
  // Always call both hooks to satisfy Rules of Hooks
@@ -1239,9 +1232,9 @@ function UnifiedCAMSProvider(props) {
1239
1232
  if (props.mode === "MSAL") {
1240
1233
  var msalConfig = props.msalConfig, msalInstance = props.msalInstance;
1241
1234
  var instance = msalInstance || new msalBrowser.PublicClientApplication(msalConfig);
1242
- return (jsxRuntimeExports.jsx(msalReact.MsalProvider, { instance: instance, children: jsxRuntimeExports.jsx(CAMSProviderInner, __assign({}, props)) }));
1235
+ return (jsxRuntimeExports.jsx(msalReact.MsalProvider, { instance: instance, children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
1243
1236
  }
1244
- return jsxRuntimeExports.jsx(CAMSProviderInner, __assign({}, props));
1237
+ return (jsxRuntimeExports.jsx(ClientOnly, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(CAMSProviderCore, __assign({}, props)) }));
1245
1238
  }
1246
1239
  // Backward compatibility exports
1247
1240
  var CAMSProvider = function (props) { return (jsxRuntimeExports.jsx(UnifiedCAMSProvider, __assign({}, props, { mode: "REGULAR" }))); };
@@ -1765,8 +1758,23 @@ var MFAOptions = function (_a) {
1765
1758
  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" })] })] }));
1766
1759
  };
1767
1760
 
1761
+ var LoginButton = function () {
1762
+ var context = useCAMSContext();
1763
+ var login = context.login, isLoading = context.isLoading, error = context.error, authMode = context.authMode;
1764
+ var handleLogin = function () {
1765
+ if (authMode === "MSAL") {
1766
+ login();
1767
+ }
1768
+ else {
1769
+ // For regular mode, you'd need to provide CAMSConfig
1770
+ console.warn("Regular CAMS login requires configuration");
1771
+ }
1772
+ };
1773
+ return (jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-4 p-6", children: [jsxRuntimeExports.jsx(Button, { onClick: handleLogin, disabled: isLoading, className: "min-w-[200px]", children: isLoading ? 'Logging in...' : 'Login with Microsoft' }), error && (jsxRuntimeExports.jsxs("p", { className: "text-red-600 text-sm text-center", children: ["Error: ", error.message] }))] }));
1774
+ };
1775
+
1768
1776
  var MFAGate = function (_a) {
1769
- var children = _a.children, fallback = _a.fallback;
1777
+ var children = _a.children, fallback = _a.fallback, LoginComponent = _a.loginComponent;
1770
1778
  var context = useCAMSContext();
1771
1779
  // Only apply MFA gate for MSAL mode
1772
1780
  if (context.authMode !== "MSAL") {
@@ -1784,7 +1792,7 @@ var MFAGate = function (_a) {
1784
1792
  } }));
1785
1793
  }
1786
1794
  if (!isAuthenticated) {
1787
- return fallback || jsxRuntimeExports.jsx("div", { children: "Please log in" });
1795
+ return fallback || (LoginComponent ? jsxRuntimeExports.jsx(LoginComponent, {}) : jsxRuntimeExports.jsx(LoginButton, {}));
1788
1796
  }
1789
1797
  return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
1790
1798
  };
@@ -1792,6 +1800,7 @@ var MFAGate = function (_a) {
1792
1800
  exports.CAMSMSALProvider = CAMSMSALProvider;
1793
1801
  exports.CAMSProvider = CAMSProvider;
1794
1802
  exports.ClientOnly = ClientOnly;
1803
+ exports.LoginButton = LoginButton;
1795
1804
  exports.MFAGate = MFAGate;
1796
1805
  exports.MFAOptions = MFAOptions;
1797
1806
  exports.ProtectedRoute = ProtectedRoute;