@nibssplc/cams-sdk-react 0.0.1-beta.89 → 0.0.1-beta.90

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.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Initiates the WebAuthn registration process.
3
+ * It takes server-provided options, converts them for the browser API,
4
+ * calls navigator.credentials.create(), and then converts the result
5
+ * back into a JSON-friendly format.
6
+ *
7
+ * @param options - The PublicKeyCredentialCreationOptions from the server.
8
+ * @returns A promise that resolves to a JSON-serializable representation of the PublicKeyCredential.
9
+ */
10
+ export declare function register(options: PublicKeyCredentialCreationOptions): Promise<PublicKeyCredential>;
11
+ /**
12
+ * Initiates the WebAuthn authentication process.
13
+ * It takes server-provided options, converts them for the browser API,
14
+ * calls navigator.credentials.get(), and then converts the result
15
+ * back into a JSON-friendly format.
16
+ *
17
+ * @param options - The PublicKeyCredentialRequestOptions from the server.
18
+ * @returns A promise that resolves to a JSON-serializable representation of the PublicKeyCredential.
19
+ */
20
+ export declare function authenticate(options: PublicKeyCredentialRequestOptions): Promise<PublicKeyCredential>;
@@ -0,0 +1,9 @@
1
+ import { register, authenticate } from '../components/CoreFIDO';
2
+ /**
3
+ * A React hook that provides access to the WebAuthn `register` and `authenticate` functions.
4
+ * @returns An object containing the `register` and `authenticate` functions.
5
+ */
6
+ export declare const useWebAuthn: () => {
7
+ register: typeof register;
8
+ authenticate: typeof authenticate;
9
+ };
package/dist/index.cjs.js CHANGED
@@ -535,6 +535,128 @@ function useCAMSMSALAuth(options) {
535
535
  };
536
536
  }
537
537
 
538
+ /**
539
+ * Converts a base64url-encoded string to an ArrayBuffer.
540
+ * @param base64url The base64url-encoded string
541
+ */
542
+ function base64urlToArrayBuffer(base64url) {
543
+ var base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
544
+ var padLength = (4 - (base64.length % 4)) % 4;
545
+ var padded = base64 + "=".repeat(padLength);
546
+ var binaryStr = atob(padded);
547
+ var buffer = new ArrayBuffer(binaryStr.length);
548
+ var bytes = new Uint8Array(buffer);
549
+ for (var i = 0; i < binaryStr.length; i++) {
550
+ bytes[i] = binaryStr.charCodeAt(i);
551
+ }
552
+ return buffer;
553
+ }
554
+ /**
555
+ * Converts an ArrayBuffer to a base64url-encoded string.
556
+ * @param buffer The ArrayBuffer to convert
557
+ */
558
+ function arrayBufferToBase64url(buffer) {
559
+ var bytes = new Uint8Array(buffer);
560
+ var binaryStr = String.fromCharCode.apply(null, bytes);
561
+ return btoa(binaryStr)
562
+ .replace(/\+/g, "-")
563
+ .replace(/\//g, "_")
564
+ .replace(/=/g, "");
565
+ }
566
+
567
+ /**
568
+ * Initiates the WebAuthn registration process.
569
+ * It takes server-provided options, converts them for the browser API,
570
+ * calls navigator.credentials.create(), and then converts the result
571
+ * back into a JSON-friendly format.
572
+ *
573
+ * @param options - The PublicKeyCredentialCreationOptions from the server.
574
+ * @returns A promise that resolves to a JSON-serializable representation of the PublicKeyCredential.
575
+ */
576
+ function register(options) {
577
+ return __awaiter(this, void 0, void 0, function () {
578
+ var createOptions, credential, publicKeyCredential, attestationResponse;
579
+ return __generator(this, function (_a) {
580
+ switch (_a.label) {
581
+ case 0:
582
+ createOptions = __assign(__assign({}, options), { challenge: base64urlToArrayBuffer(options.challenge), user: __assign(__assign({}, options.user), { id: base64urlToArrayBuffer(options.user.id) }) });
583
+ return [4 /*yield*/, navigator.credentials.create({
584
+ publicKey: createOptions,
585
+ })];
586
+ case 1:
587
+ credential = _a.sent();
588
+ if (!credential) {
589
+ throw new Error("Failed to create credential.");
590
+ }
591
+ publicKeyCredential = credential;
592
+ attestationResponse = publicKeyCredential.response;
593
+ return [2 /*return*/, {
594
+ id: publicKeyCredential.id,
595
+ rawId: arrayBufferToBase64url(publicKeyCredential.rawId),
596
+ type: credential.type,
597
+ response: {
598
+ clientDataJSON: arrayBufferToBase64url(attestationResponse.clientDataJSON),
599
+ attestationObject: arrayBufferToBase64url(attestationResponse.attestationObject),
600
+ },
601
+ }];
602
+ }
603
+ });
604
+ });
605
+ }
606
+ /**
607
+ * Initiates the WebAuthn authentication process.
608
+ * It takes server-provided options, converts them for the browser API,
609
+ * calls navigator.credentials.get(), and then converts the result
610
+ * back into a JSON-friendly format.
611
+ *
612
+ * @param options - The PublicKeyCredentialRequestOptions from the server.
613
+ * @returns A promise that resolves to a JSON-serializable representation of the PublicKeyCredential.
614
+ */
615
+ function authenticate(options) {
616
+ return __awaiter(this, void 0, void 0, function () {
617
+ var getOptions, credential, publicKeyCredential, assertionResponse;
618
+ var _a;
619
+ return __generator(this, function (_b) {
620
+ switch (_b.label) {
621
+ case 0:
622
+ getOptions = __assign(__assign({}, options), { challenge: base64urlToArrayBuffer(options.challenge), allowCredentials: (_a = options.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(function (cred) { return (__assign(__assign({}, cred), { id: base64urlToArrayBuffer(cred.id) })); }) });
623
+ return [4 /*yield*/, navigator.credentials.get({ publicKey: getOptions })];
624
+ case 1:
625
+ credential = _b.sent();
626
+ if (!credential) {
627
+ throw new Error("Failed to get credential.");
628
+ }
629
+ publicKeyCredential = credential;
630
+ assertionResponse = publicKeyCredential.response;
631
+ return [2 /*return*/, {
632
+ id: publicKeyCredential.id,
633
+ rawId: arrayBufferToBase64url(publicKeyCredential.rawId),
634
+ type: credential.type,
635
+ response: {
636
+ clientDataJSON: arrayBufferToBase64url(assertionResponse.clientDataJSON),
637
+ authenticatorData: arrayBufferToBase64url(assertionResponse.authenticatorData),
638
+ signature: arrayBufferToBase64url(assertionResponse.signature),
639
+ userHandle: assertionResponse.userHandle
640
+ ? arrayBufferToBase64url(assertionResponse.userHandle)
641
+ : null,
642
+ },
643
+ }];
644
+ }
645
+ });
646
+ });
647
+ }
648
+
649
+ /**
650
+ * A React hook that provides access to the WebAuthn `register` and `authenticate` functions.
651
+ * @returns An object containing the `register` and `authenticate` functions.
652
+ */
653
+ var useWebAuthn = function () {
654
+ return {
655
+ register: register,
656
+ authenticate: authenticate,
657
+ };
658
+ };
659
+
538
660
  var jsxRuntime = {exports: {}};
539
661
 
540
662
  var reactJsxRuntime_production = {};
@@ -1915,7 +2037,8 @@ var DefaultLoginPage = function () {
1915
2037
  var context = useCAMSContext();
1916
2038
  var login = context.login, isLoading = context.isLoading, authMode = context.authMode;
1917
2039
  var _a = React.useState(false), showADModal = _a[0], setShowADModal = _a[1];
1918
- var handleLogin = function () {
2040
+ var _b = useWebAuthn(), register = _b.register, authenticate = _b.authenticate;
2041
+ var handleMSALLogin = function () {
1919
2042
  if (authMode === "MSAL") {
1920
2043
  login();
1921
2044
  }
@@ -1934,15 +2057,105 @@ var DefaultLoginPage = function () {
1934
2057
  },
1935
2058
  exit: { opacity: 0, scale: 0.8, y: -50, transition: { duration: 0.3 } },
1936
2059
  };
1937
- return (jsxRuntimeExports.jsxs("main", { className: "min-h-screen bg-gray-50", children: [jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.5 }, children: jsxRuntimeExports.jsx("div", { className: "flex h-screen items-center justify-center", children: jsxRuntimeExports.jsxs(framerMotion.motion.div, { variants: cardVariants, initial: "hidden", animate: "visible", exit: "exit", className: "w-full max-w-md p-6 space-y-4 bg-gray-50 rounded-2xl shadow-2xl --dark:bg-gray-800", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "text-center space-y-3", children: [jsxRuntimeExports.jsx("div", { className: "w-full flex items-center justify-center", children: jsxRuntimeExports.jsx("img", { src: NIBSSLogo, alt: "NIBSS Logo", width: 265, height: 265 }) }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold --text-gray-900 --dark:text-white", children: "NIBSS CAMS" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-500 dark:text-gray-400 font-bold text-lg", children: "Centralized Authentication" })] }), jsxRuntimeExports.jsxs(CardAction, { className: "w-full flex flex-col items-center justify-center text-center text-gray-500 dark:text-gray-400 mb-4", children: [jsxRuntimeExports.jsx("img", { src: AuthLogo, alt: "Auth Logo", width: 365, height: 365 }), "Kindly use the below identity providers to authenticate"] }), jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsxs(Button
2060
+ var handleRegister = function () { return __awaiter(void 0, void 0, void 0, function () {
2061
+ var res, options, attestationResponse, error_1;
2062
+ return __generator(this, function (_a) {
2063
+ switch (_a.label) {
2064
+ case 0:
2065
+ _a.trys.push([0, 5, , 6]);
2066
+ // 1. Fetch challenge from your server
2067
+ console.log("Requesting registration challenge from server...");
2068
+ return [4 /*yield*/, fetch("/api/webauthn/register-challenge")];
2069
+ case 1:
2070
+ res = _a.sent();
2071
+ return [4 /*yield*/, res.json()];
2072
+ case 2:
2073
+ options = _a.sent();
2074
+ console.log("Received challenge:", options);
2075
+ // 2. Call the SDK to trigger the browser's passkey creation UI
2076
+ console.log("Calling SDK register function...");
2077
+ return [4 /*yield*/, register(options)];
2078
+ case 3:
2079
+ attestationResponse = _a.sent();
2080
+ console.log("Passkey created on client:", attestationResponse);
2081
+ // 3. Send the response back to the server for verification
2082
+ console.log("Sending attestation to server for verification...");
2083
+ return [4 /*yield*/, fetch("/api/webauthn/register-verify", {
2084
+ method: "POST",
2085
+ headers: { "Content-Type": "application/json" },
2086
+ body: JSON.stringify(attestationResponse),
2087
+ })];
2088
+ case 4:
2089
+ _a.sent();
2090
+ alert("✅ Registration successful! Passkey created.");
2091
+ return [3 /*break*/, 6];
2092
+ case 5:
2093
+ error_1 = _a.sent();
2094
+ console.error("Registration failed:", error_1);
2095
+ alert("❌ Could not create passkey.");
2096
+ return [3 /*break*/, 6];
2097
+ case 6: return [2 /*return*/];
2098
+ }
2099
+ });
2100
+ }); };
2101
+ var handleFIDOLogin = function () { return __awaiter(void 0, void 0, void 0, function () {
2102
+ var res, options, assertionResponse, error_2;
2103
+ return __generator(this, function (_a) {
2104
+ switch (_a.label) {
2105
+ case 0:
2106
+ _a.trys.push([0, 5, , 6]);
2107
+ // 1. Fetch authentication challenge from your server
2108
+ console.log("Requesting authentication challenge from server...");
2109
+ return [4 /*yield*/, fetch("/api/webauthn/auth-challenge")];
2110
+ case 1:
2111
+ res = _a.sent();
2112
+ return [4 /*yield*/, res.json()];
2113
+ case 2:
2114
+ options = _a.sent();
2115
+ console.log("Received challenge:", options);
2116
+ // 2. Call the SDK to trigger the browser's passkey authentication UI
2117
+ console.log("Calling SDK authenticate function...");
2118
+ return [4 /*yield*/, authenticate(options)];
2119
+ case 3:
2120
+ assertionResponse = _a.sent();
2121
+ console.log("Authentication assertion received from client:", assertionResponse);
2122
+ // 3. Send the assertion back to the server for verification
2123
+ console.log("Sending assertion to server for verification...");
2124
+ return [4 /*yield*/, fetch("/api/webauthn/auth-verify", {
2125
+ method: "POST",
2126
+ headers: { "Content-Type": "application/json" },
2127
+ body: JSON.stringify(assertionResponse),
2128
+ })];
2129
+ case 4:
2130
+ _a.sent();
2131
+ alert("🔑 Sign-in successful!");
2132
+ return [3 /*break*/, 6];
2133
+ case 5:
2134
+ error_2 = _a.sent();
2135
+ console.error("Authentication failed:", error_2);
2136
+ alert("❌ Could not sign in.");
2137
+ return [3 /*break*/, 6];
2138
+ case 6: return [2 /*return*/];
2139
+ }
2140
+ });
2141
+ }); };
2142
+ return (jsxRuntimeExports.jsxs("main", { className: "min-h-screen bg-gray-50", children: [jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.5 }, children: jsxRuntimeExports.jsx("div", { className: "flex h-screen items-center justify-center", children: jsxRuntimeExports.jsxs(framerMotion.motion.div, { variants: cardVariants, initial: "hidden", animate: "visible", exit: "exit", className: "w-full max-w-md p-6 space-y-4 bg-gray-50 rounded-2xl shadow-2xl --dark:bg-gray-800", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "text-center space-y-3", children: [jsxRuntimeExports.jsx("div", { className: "w-full flex items-center justify-center", children: jsxRuntimeExports.jsx("img", { src: NIBSSLogo, alt: "NIBSS Logo", width: 265, height: 265 }) }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold --text-gray-900 --dark:text-white", children: "NIBSS CAMS" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-500 dark:text-gray-400 font-bold text-lg", children: "Centralized Authentication" })] }), jsxRuntimeExports.jsxs(CardAction, { className: "w-full flex flex-col items-center justify-center text-center text-gray-500 dark:text-gray-400 mb-6", children: [jsxRuntimeExports.jsx("img", { src: AuthLogo, alt: "Auth Logo", width: 365, height: 365 }), "Kindly use the below identity providers to authenticate"] }), jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsxs(Button
2143
+ // variant="outline"
2144
+ , {
2145
+ // variant="outline"
2146
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: handleMSALLogin, disabled: isLoading, children: [jsxRuntimeExports.jsx("img", { src: MicrosoftLogo, alt: "Microsoft Logo", width: 35, height: 35 }), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with Microsoft" })] }), jsxRuntimeExports.jsxs(Button
2147
+ // variant="outline"
2148
+ , {
2149
+ // variant="outline"
2150
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: function () { return setShowADModal(true); }, disabled: isLoading, children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, { className: "w-8 h-8 text-[#506f4a]" }), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with ActiveDirectory" })] }), jsxRuntimeExports.jsxs(Button
1938
2151
  // variant="outline"
1939
2152
  , {
1940
2153
  // variant="outline"
1941
- className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: handleLogin, disabled: isLoading, children: [jsxRuntimeExports.jsx("img", { src: MicrosoftLogo, alt: "Microsoft Logo", width: 35, height: 35 }), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with Microsoft" })] }), jsxRuntimeExports.jsxs(Button
2154
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: function () { return handleRegister; }, disabled: isLoading, children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, { className: "w-8 h-8 text-[#506f4a]" }), jsxRuntimeExports.jsx("span", { children: "Create a Passkey" })] }), jsxRuntimeExports.jsxs(Button
1942
2155
  // variant="outline"
1943
2156
  , {
1944
2157
  // variant="outline"
1945
- className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: function () { return setShowADModal(true); }, disabled: isLoading, children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, { className: "w-8 h-8 text-[#506f4a]" }), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with ActiveDirectory" })] })] }), 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" })] })] }) }) }, "landing"), jsxRuntimeExports.jsx(ADLoginModal, { open: showADModal, onOpenChange: setShowADModal, onLogin: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
2158
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: function () { return handleFIDOLogin; }, disabled: isLoading, children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, { className: "w-8 h-8 text-[#506f4a]" }), jsxRuntimeExports.jsx("span", { children: "Sign In with Passkey" })] })] }), 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" })] })] }) }) }, "landing"), jsxRuntimeExports.jsx(ADLoginModal, { open: showADModal, onOpenChange: setShowADModal, onLogin: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
1946
2159
  var username = _b.username, password = _b.password, MFACode = _b.MFACode;
1947
2160
  return __generator(this, function (_c) {
1948
2161
  // Implement your AD login logic here
@@ -2009,10 +2222,13 @@ exports.MFAGate = MFAGate;
2009
2222
  exports.MFAOptions = MFAOptions;
2010
2223
  exports.ProtectedRoute = ProtectedRoute;
2011
2224
  exports.UnifiedCAMSProvider = UnifiedCAMSProvider;
2225
+ exports.authenticate = authenticate;
2226
+ exports.register = register;
2012
2227
  exports.useCAMSAuth = useCAMSAuth;
2013
2228
  exports.useCAMSContext = useCAMSContext;
2014
2229
  exports.useCAMSMSALAuth = useCAMSMSALAuth;
2015
2230
  exports.useCAMSMSALContext = useCAMSMSALContext;
2231
+ exports.useWebAuthn = useWebAuthn;
2016
2232
  Object.keys(camsSdk).forEach(function (k) {
2017
2233
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
2018
2234
  enumerable: true,