nid-webauthn-emulator 0.1.3

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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/spec/authenticator/authenticator-emulator.spec.d.ts +1 -0
  4. package/dist/spec/authenticator/authenticator-emulator.spec.js +18 -0
  5. package/dist/spec/authenticator/ctap-model.spec.d.ts +1 -0
  6. package/dist/spec/authenticator/ctap-model.spec.js +95 -0
  7. package/dist/spec/integration/integration.spec.d.ts +1 -0
  8. package/dist/spec/integration/integration.spec.js +32 -0
  9. package/dist/spec/integration/passkeys-api-client.d.ts +11 -0
  10. package/dist/spec/integration/passkeys-api-client.js +2 -0
  11. package/dist/spec/integration/webauthn-io.d.ts +32 -0
  12. package/dist/spec/integration/webauthn-io.js +100 -0
  13. package/dist/spec/libs/browser-injection.spec.d.ts +1 -0
  14. package/dist/spec/libs/browser-injection.spec.js +15 -0
  15. package/dist/spec/libs/cose-key.spec.d.ts +1 -0
  16. package/dist/spec/libs/cose-key.spec.js +47 -0
  17. package/dist/spec/repository/credential-repository.spec.d.ts +1 -0
  18. package/dist/spec/repository/credential-repository.spec.js +96 -0
  19. package/dist/spec/webauthn/cose-key.spec.d.ts +1 -0
  20. package/dist/spec/webauthn/cose-key.spec.js +74 -0
  21. package/dist/spec/webauthn/webauthn-emulator.spec.d.ts +1 -0
  22. package/dist/spec/webauthn/webauthn-emulator.spec.js +222 -0
  23. package/dist/spec/webauthn/webauthn-model-json.spec.d.ts +1 -0
  24. package/dist/spec/webauthn/webauthn-model-json.spec.js +103 -0
  25. package/dist/spec/webauthn/webauthn-model.spec.d.ts +1 -0
  26. package/dist/spec/webauthn/webauthn-model.spec.js +97 -0
  27. package/dist/spec/webauthn/webauthn-test-server.d.ts +15 -0
  28. package/dist/spec/webauthn/webauthn-test-server.js +87 -0
  29. package/dist/src/authenticator/authenticator-emulator.d.ts +68 -0
  30. package/dist/src/authenticator/authenticator-emulator.js +304 -0
  31. package/dist/src/authenticator/ctap-model.d.ts +107 -0
  32. package/dist/src/authenticator/ctap-model.js +202 -0
  33. package/dist/src/index.d.ts +16 -0
  34. package/dist/src/index.js +34 -0
  35. package/dist/src/libs/encode-utils.d.ts +15 -0
  36. package/dist/src/libs/encode-utils.js +92 -0
  37. package/dist/src/repository/credentials-file-repository.d.ts +8 -0
  38. package/dist/src/repository/credentials-file-repository.js +62 -0
  39. package/dist/src/repository/credentials-memory-repository.d.ts +7 -0
  40. package/dist/src/repository/credentials-memory-repository.js +20 -0
  41. package/dist/src/repository/credentials-repository.d.ts +39 -0
  42. package/dist/src/repository/credentials-repository.js +46 -0
  43. package/dist/src/test-utils/browser-injection.d.ts +3 -0
  44. package/dist/src/test-utils/browser-injection.js +52 -0
  45. package/dist/src/webauthn/cose-key.d.ts +16 -0
  46. package/dist/src/webauthn/cose-key.js +151 -0
  47. package/dist/src/webauthn/webauthn-emulator.d.ts +30 -0
  48. package/dist/src/webauthn/webauthn-emulator.js +142 -0
  49. package/dist/src/webauthn/webauthn-model-json.d.ts +101 -0
  50. package/dist/src/webauthn/webauthn-model-json.js +187 -0
  51. package/dist/src/webauthn/webauthn-model.d.ts +68 -0
  52. package/dist/src/webauthn/webauthn-model.js +186 -0
  53. package/package.json +37 -0
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AuthenticationEmulatorError = exports.CTAP_COMMAND = exports.CTAP_STATUS_CODE = void 0;
7
+ exports.unpackRequest = unpackRequest;
8
+ exports.packMakeCredentialRequest = packMakeCredentialRequest;
9
+ exports.packGetAssertionRequest = packGetAssertionRequest;
10
+ exports.unpackMakeCredentialResponse = unpackMakeCredentialResponse;
11
+ exports.packMakeCredentialResponse = packMakeCredentialResponse;
12
+ exports.unpackGetAssertionResponse = unpackGetAssertionResponse;
13
+ exports.packGetAssertionResponse = packGetAssertionResponse;
14
+ exports.unpackGetInfoResponse = unpackGetInfoResponse;
15
+ exports.packGetInfoResponse = packGetInfoResponse;
16
+ const encode_utils_1 = __importDefault(require("../libs/encode-utils"));
17
+ /** @see https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#error-responses */
18
+ var CTAP_STATUS_CODE;
19
+ (function (CTAP_STATUS_CODE) {
20
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_OK"] = 0] = "CTAP2_OK";
21
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP1_ERR_INVALID_COMMAND"] = 1] = "CTAP1_ERR_INVALID_COMMAND";
22
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP1_ERR_INVALID_PARAMETER"] = 2] = "CTAP1_ERR_INVALID_PARAMETER";
23
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_INVALID_CBOR"] = 18] = "CTAP2_ERR_INVALID_CBOR";
24
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_CREDENTIAL_EXCLUDED"] = 25] = "CTAP2_ERR_CREDENTIAL_EXCLUDED";
25
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_UNSUPPORTED_ALGORITHM"] = 38] = "CTAP2_ERR_UNSUPPORTED_ALGORITHM";
26
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_OPERATION_DENIED"] = 39] = "CTAP2_ERR_OPERATION_DENIED";
27
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_NO_CREDENTIALS"] = 46] = "CTAP2_ERR_NO_CREDENTIALS";
28
+ CTAP_STATUS_CODE[CTAP_STATUS_CODE["CTAP2_ERR_NOT_ALLOWED"] = 48] = "CTAP2_ERR_NOT_ALLOWED";
29
+ })(CTAP_STATUS_CODE || (exports.CTAP_STATUS_CODE = CTAP_STATUS_CODE = {}));
30
+ /** @see https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#commands */
31
+ var CTAP_COMMAND;
32
+ (function (CTAP_COMMAND) {
33
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorMakeCredential"] = 1] = "authenticatorMakeCredential";
34
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorGetAssertion"] = 2] = "authenticatorGetAssertion";
35
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorGetInfo"] = 4] = "authenticatorGetInfo";
36
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorClientPIN"] = 6] = "authenticatorClientPIN";
37
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorReset"] = 7] = "authenticatorReset";
38
+ CTAP_COMMAND[CTAP_COMMAND["authenticatorGetNextAssertion"] = 8] = "authenticatorGetNextAssertion";
39
+ })(CTAP_COMMAND || (exports.CTAP_COMMAND = CTAP_COMMAND = {}));
40
+ // Not standard functions and interfaces
41
+ class AuthenticationEmulatorError extends Error {
42
+ status;
43
+ type = "CTAPError";
44
+ constructor(status, options) {
45
+ super(`CTAP error: ${CTAP_STATUS_CODE[status]} (${status})`, options);
46
+ this.status = status;
47
+ }
48
+ }
49
+ exports.AuthenticationEmulatorError = AuthenticationEmulatorError;
50
+ function unpackRequest(request) {
51
+ let data = {};
52
+ try {
53
+ data = (request.data ? encode_utils_1.default.decodeCbor(request.data) : {});
54
+ }
55
+ catch (error) {
56
+ throw new AuthenticationEmulatorError(CTAP_STATUS_CODE.CTAP2_ERR_INVALID_CBOR, { cause: error });
57
+ }
58
+ switch (request.command) {
59
+ case CTAP_COMMAND.authenticatorMakeCredential:
60
+ return {
61
+ command: request.command,
62
+ request: {
63
+ clientDataHash: encode_utils_1.default.bufferSourceToUint8Array(data[0x01]),
64
+ rp: data[0x02],
65
+ user: data[0x03],
66
+ pubKeyCredParams: data[0x04],
67
+ excludeList: data[0x05],
68
+ extensions: data[0x06],
69
+ options: data[0x07],
70
+ pinAuth: data[0x08] ? encode_utils_1.default.bufferSourceToUint8Array(data[0x08]) : undefined,
71
+ pinProtocol: data[0x09],
72
+ },
73
+ };
74
+ case CTAP_COMMAND.authenticatorGetAssertion:
75
+ return {
76
+ command: request.command,
77
+ request: {
78
+ rpId: data[0x01],
79
+ clientDataHash: encode_utils_1.default.bufferSourceToUint8Array(data[0x02]),
80
+ allowList: data[0x03],
81
+ extensions: data[0x04],
82
+ options: data[0x05],
83
+ pinAuth: data[0x06] ? encode_utils_1.default.bufferSourceToUint8Array(data[0x06]) : undefined,
84
+ pinProtocol: data[0x07],
85
+ },
86
+ };
87
+ default:
88
+ return {
89
+ command: request.command,
90
+ request: undefined,
91
+ };
92
+ }
93
+ }
94
+ function packMakeCredentialRequest(request) {
95
+ return {
96
+ command: CTAP_COMMAND.authenticatorMakeCredential,
97
+ data: encode_utils_1.default.encodeCbor({
98
+ [0x01]: request.clientDataHash,
99
+ [0x02]: request.rp,
100
+ [0x03]: request.user,
101
+ [0x04]: request.pubKeyCredParams,
102
+ [0x05]: request.excludeList,
103
+ [0x06]: request.extensions,
104
+ [0x07]: request.options,
105
+ [0x08]: request.pinAuth,
106
+ [0x09]: request.pinProtocol,
107
+ }),
108
+ };
109
+ }
110
+ function packGetAssertionRequest(request) {
111
+ return {
112
+ command: CTAP_COMMAND.authenticatorGetAssertion,
113
+ data: encode_utils_1.default.encodeCbor({
114
+ [0x01]: request.rpId,
115
+ [0x02]: request.clientDataHash,
116
+ [0x03]: request.allowList,
117
+ [0x04]: request.extensions,
118
+ [0x05]: request.options,
119
+ [0x06]: request.pinAuth,
120
+ [0x07]: request.pinProtocol,
121
+ }),
122
+ };
123
+ }
124
+ function unpackMakeCredentialResponse(response) {
125
+ try {
126
+ const data = encode_utils_1.default.decodeCbor(response.data);
127
+ return {
128
+ fmt: data[0x01],
129
+ authData: encode_utils_1.default.bufferSourceToUint8Array(data[0x02]),
130
+ attStmt: data[0x03],
131
+ };
132
+ }
133
+ catch (error) {
134
+ throw new AuthenticationEmulatorError(CTAP_STATUS_CODE.CTAP2_ERR_INVALID_CBOR, { cause: error });
135
+ }
136
+ }
137
+ function packMakeCredentialResponse(response) {
138
+ return {
139
+ status: CTAP_STATUS_CODE.CTAP2_OK,
140
+ data: encode_utils_1.default.encodeCbor({
141
+ [0x01]: response.fmt,
142
+ [0x02]: response.authData,
143
+ [0x03]: response.attStmt,
144
+ }),
145
+ };
146
+ }
147
+ function unpackGetAssertionResponse(response) {
148
+ try {
149
+ const data = encode_utils_1.default.decodeCbor(response.data);
150
+ return {
151
+ credential: data[0x01],
152
+ authData: encode_utils_1.default.bufferSourceToUint8Array(data[0x02]),
153
+ signature: encode_utils_1.default.bufferSourceToUint8Array(data[0x03]),
154
+ user: data[0x04],
155
+ numberOfCredentials: data[0x05],
156
+ };
157
+ }
158
+ catch (error) {
159
+ throw new AuthenticationEmulatorError(CTAP_STATUS_CODE.CTAP2_ERR_INVALID_CBOR, { cause: error });
160
+ }
161
+ }
162
+ function packGetAssertionResponse(response) {
163
+ return {
164
+ status: CTAP_STATUS_CODE.CTAP2_OK,
165
+ data: encode_utils_1.default.encodeCbor({
166
+ [0x01]: response.credential,
167
+ [0x02]: response.authData,
168
+ [0x03]: response.signature,
169
+ [0x04]: response.user,
170
+ [0x05]: response.numberOfCredentials,
171
+ }),
172
+ };
173
+ }
174
+ function unpackGetInfoResponse(response) {
175
+ try {
176
+ const data = encode_utils_1.default.decodeCbor(response.data);
177
+ return {
178
+ versions: data[0x01],
179
+ extensions: data[0x02],
180
+ aaguid: encode_utils_1.default.bufferSourceToUint8Array(data[0x03]),
181
+ options: data[0x04],
182
+ maxMsgSize: data[0x05],
183
+ pinProtocols: data[0x06],
184
+ };
185
+ }
186
+ catch (error) {
187
+ throw new AuthenticationEmulatorError(CTAP_STATUS_CODE.CTAP2_ERR_INVALID_CBOR, { cause: error });
188
+ }
189
+ }
190
+ function packGetInfoResponse(response) {
191
+ return {
192
+ status: CTAP_STATUS_CODE.CTAP2_OK,
193
+ data: encode_utils_1.default.encodeCbor({
194
+ [0x01]: response.versions,
195
+ [0x02]: response.extensions,
196
+ [0x03]: response.aaguid,
197
+ [0x04]: response.options,
198
+ [0x05]: response.maxMsgSize,
199
+ [0x06]: response.pinProtocols,
200
+ }),
201
+ };
202
+ }
@@ -0,0 +1,16 @@
1
+ import { WebAuthnEmulator } from "./webauthn/webauthn-emulator";
2
+ export default WebAuthnEmulator;
3
+ export * from "./webauthn/webauthn-model-json";
4
+ export * from "./webauthn/webauthn-model";
5
+ export * from "./webauthn/webauthn-emulator";
6
+ export * from "./webauthn/cose-key";
7
+ export * from "./authenticator/authenticator-emulator";
8
+ export * from "./authenticator/ctap-model";
9
+ export * from "./repository/credentials-repository";
10
+ export * from "./repository/credentials-file-repository";
11
+ export * from "./repository/credentials-memory-repository";
12
+ export declare const BrowserInjection: {
13
+ WebAuthnEmulatorGet: string;
14
+ WebAuthnEmulatorCreate: string;
15
+ HookWebAuthnApis: string;
16
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.BrowserInjection = void 0;
18
+ const browser_injection_1 = require("./test-utils/browser-injection");
19
+ const webauthn_emulator_1 = require("./webauthn/webauthn-emulator");
20
+ exports.default = webauthn_emulator_1.WebAuthnEmulator;
21
+ __exportStar(require("./webauthn/webauthn-model-json"), exports);
22
+ __exportStar(require("./webauthn/webauthn-model"), exports);
23
+ __exportStar(require("./webauthn/webauthn-emulator"), exports);
24
+ __exportStar(require("./webauthn/cose-key"), exports);
25
+ __exportStar(require("./authenticator/authenticator-emulator"), exports);
26
+ __exportStar(require("./authenticator/ctap-model"), exports);
27
+ __exportStar(require("./repository/credentials-repository"), exports);
28
+ __exportStar(require("./repository/credentials-file-repository"), exports);
29
+ __exportStar(require("./repository/credentials-memory-repository"), exports);
30
+ exports.BrowserInjection = {
31
+ WebAuthnEmulatorGet: browser_injection_1.WebAuthnEmulatorGet,
32
+ WebAuthnEmulatorCreate: browser_injection_1.WebAuthnEmulatorCreate,
33
+ HookWebAuthnApis: browser_injection_1.HookWebAuthnApis,
34
+ };
@@ -0,0 +1,15 @@
1
+ declare function encodeBase64Url(data: BufferSource): string;
2
+ declare function decodeBase64Url(base64Url: string): Uint8Array;
3
+ declare function bufferSourceToUint8Array(data: BufferSource): Uint8Array;
4
+ declare function strToUint8Array(data: string): Uint8Array;
5
+ declare function encodeCbor(data: object): Uint8Array;
6
+ declare function decodeCbor<T>(data: Uint8Array): T;
7
+ declare const EncodeUtils: {
8
+ strToUint8Array: typeof strToUint8Array;
9
+ bufferSourceToUint8Array: typeof bufferSourceToUint8Array;
10
+ encodeBase64Url: typeof encodeBase64Url;
11
+ decodeBase64Url: typeof decodeBase64Url;
12
+ encodeCbor: typeof encodeCbor;
13
+ decodeCbor: typeof decodeCbor;
14
+ };
15
+ export default EncodeUtils;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cbor_1 = __importDefault(require("cbor"));
7
+ function encodeBase64Url(data) {
8
+ const buffer = bufferSourceToUint8Array(data);
9
+ let binaryString = "";
10
+ for (let i = 0; i < buffer.length; i++) {
11
+ binaryString += String.fromCharCode(buffer[i]);
12
+ }
13
+ return btoa(binaryString).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
14
+ }
15
+ function decodeBase64Url(base64Url) {
16
+ const binaryString = atob(base64Url.replace(/-/g, "+").replace(/_/g, "/"));
17
+ const bytes = new Uint8Array(binaryString.length);
18
+ for (let i = 0; i < binaryString.length; i++) {
19
+ bytes[i] = binaryString.charCodeAt(i);
20
+ }
21
+ return bytes;
22
+ }
23
+ function bufferSourceToUint8Array(data) {
24
+ if (data instanceof ArrayBuffer) {
25
+ return new Uint8Array(data);
26
+ }
27
+ return new Uint8Array(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
28
+ }
29
+ function strToUint8Array(data) {
30
+ return new Uint8Array(data.split("").map((c) => c.charCodeAt(0)));
31
+ }
32
+ function encodeCbor(data) {
33
+ function encoder(value) {
34
+ if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
35
+ return Buffer.from(value);
36
+ }
37
+ if (Array.isArray(value)) {
38
+ return value.map((v) => encoder(v));
39
+ }
40
+ if (typeof value === "object" && value !== null) {
41
+ const encodedData = new Map();
42
+ for (const [k, v] of Object.entries(value)) {
43
+ const ki = Number.parseInt(k);
44
+ if (Number.isNaN(ki)) {
45
+ encodedData.set(k, encoder(v));
46
+ }
47
+ else {
48
+ encodedData.set(ki, encoder(v));
49
+ }
50
+ }
51
+ return encodedData;
52
+ }
53
+ return value;
54
+ }
55
+ return new Uint8Array(cbor_1.default.encode(encoder(data)));
56
+ }
57
+ function decodeCbor(data) {
58
+ const canonicalData = cbor_1.default.decode(data);
59
+ function decoder(value) {
60
+ if (value instanceof Buffer) {
61
+ return new Uint8Array(value);
62
+ }
63
+ if (Array.isArray(value)) {
64
+ return value.map((v) => decoder(v));
65
+ }
66
+ if (value instanceof Map) {
67
+ const decodedData = {};
68
+ for (const [k, v] of value) {
69
+ Object.assign(decodedData, { [k]: decoder(v) });
70
+ }
71
+ return decodedData;
72
+ }
73
+ if (typeof value === "object" && value !== null) {
74
+ const decodedData = {};
75
+ for (const [k, v] of Object.entries(value)) {
76
+ Object.assign(decodedData, { [k]: decoder(v) });
77
+ }
78
+ return decodedData;
79
+ }
80
+ return value;
81
+ }
82
+ return decoder(canonicalData);
83
+ }
84
+ const EncodeUtils = {
85
+ strToUint8Array,
86
+ bufferSourceToUint8Array,
87
+ encodeBase64Url,
88
+ decodeBase64Url,
89
+ encodeCbor,
90
+ decodeCbor,
91
+ };
92
+ exports.default = EncodeUtils;
@@ -0,0 +1,8 @@
1
+ import { type PasskeyDiscoverableCredential, type PasskeysCredentialsRepository } from "./credentials-repository";
2
+ export declare class PasskeysCredentialsFileRepository implements PasskeysCredentialsRepository {
3
+ private readonly credentialsDir;
4
+ constructor(credentialsDir?: string);
5
+ saveCredential(credential: PasskeyDiscoverableCredential): void;
6
+ deleteCredential(credential: PasskeyDiscoverableCredential): void;
7
+ loadCredentials(): PasskeyDiscoverableCredential[];
8
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.PasskeysCredentialsFileRepository = void 0;
27
+ const fs = __importStar(require("node:fs"));
28
+ const path = __importStar(require("node:path"));
29
+ const credentials_repository_1 = require("./credentials-repository");
30
+ const CREDENTIALS_DIR = path.join(__dirname, "./credentials");
31
+ class PasskeysCredentialsFileRepository {
32
+ credentialsDir;
33
+ constructor(credentialsDir = CREDENTIALS_DIR) {
34
+ this.credentialsDir = credentialsDir;
35
+ fs.mkdirSync(credentialsDir, { recursive: true });
36
+ }
37
+ saveCredential(credential) {
38
+ const id = (0, credentials_repository_1.getRepositoryId)(credential);
39
+ const filename = path.join(this.credentialsDir, `${id}.json`);
40
+ const serialized = (0, credentials_repository_1.serializeCredential)(credential);
41
+ fs.writeFileSync(filename, serialized);
42
+ }
43
+ deleteCredential(credential) {
44
+ const id = (0, credentials_repository_1.getRepositoryId)(credential);
45
+ const filename = path.join(this.credentialsDir, `${id}.json`);
46
+ fs.unlink(filename, () => { });
47
+ }
48
+ loadCredentials() {
49
+ const files = fs.readdirSync(this.credentialsDir);
50
+ return files.flatMap((file) => {
51
+ try {
52
+ const filename = path.join(this.credentialsDir, file);
53
+ const serialized = fs.readFileSync(filename, "utf-8");
54
+ return [(0, credentials_repository_1.deserializeCredential)(serialized)];
55
+ }
56
+ catch {
57
+ return [];
58
+ }
59
+ });
60
+ }
61
+ }
62
+ exports.PasskeysCredentialsFileRepository = PasskeysCredentialsFileRepository;
@@ -0,0 +1,7 @@
1
+ import { type PasskeyDiscoverableCredential, type PasskeysCredentialsRepository } from "./credentials-repository";
2
+ export declare class PasskeysCredentialsMemoryRepository implements PasskeysCredentialsRepository {
3
+ private readonly credentials;
4
+ saveCredential(credential: PasskeyDiscoverableCredential): void;
5
+ deleteCredential(credential: PasskeyDiscoverableCredential): void;
6
+ loadCredentials(): PasskeyDiscoverableCredential[];
7
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PasskeysCredentialsMemoryRepository = void 0;
4
+ const credentials_repository_1 = require("./credentials-repository");
5
+ class PasskeysCredentialsMemoryRepository {
6
+ credentials = new Map();
7
+ saveCredential(credential) {
8
+ const id = (0, credentials_repository_1.getRepositoryId)(credential);
9
+ const serialized = (0, credentials_repository_1.serializeCredential)(credential);
10
+ this.credentials.set(id, serialized);
11
+ }
12
+ deleteCredential(credential) {
13
+ const id = (0, credentials_repository_1.getRepositoryId)(credential);
14
+ this.credentials.delete(id);
15
+ }
16
+ loadCredentials() {
17
+ return Array.from(this.credentials.values()).map((serialized) => (0, credentials_repository_1.deserializeCredential)(serialized));
18
+ }
19
+ }
20
+ exports.PasskeysCredentialsMemoryRepository = PasskeysCredentialsMemoryRepository;
@@ -0,0 +1,39 @@
1
+ import { type AuthenticatorData, type PublicKeyCredentialSource, type PublicKeyCredentialSourceJSON } from "../webauthn/webauthn-model";
2
+ import { type PublicKeyCredentialDescriptorJSON, type PublicKeyCredentialUserEntityJSON } from "../webauthn/webauthn-model-json";
3
+ export type PasskeyDiscoverableCredential = {
4
+ readonly publicKeyCredentialDescriptor: PublicKeyCredentialDescriptor;
5
+ readonly publicKeyCredentialSource: PublicKeyCredentialSource;
6
+ readonly authenticatorData: AuthenticatorData;
7
+ readonly user: PublicKeyCredentialUserEntity;
8
+ };
9
+ export type PasskeyDiscoverableCredentialJSON = {
10
+ publicKeyCredentialDescriptor: PublicKeyCredentialDescriptorJSON;
11
+ publicKeyCredentialSource: PublicKeyCredentialSourceJSON;
12
+ authenticatorData: string;
13
+ user: PublicKeyCredentialUserEntityJSON;
14
+ };
15
+ /**
16
+ * Passkey credentials repository
17
+ */
18
+ export interface PasskeysCredentialsRepository {
19
+ saveCredential(credential: PasskeyDiscoverableCredential): void;
20
+ deleteCredential(credential: PasskeyDiscoverableCredential): void;
21
+ loadCredentials(): PasskeyDiscoverableCredential[];
22
+ }
23
+ /**
24
+ * Get the ID of a credential
25
+ * @param credential Credential
26
+ */
27
+ export declare function getRepositoryId(credential: PasskeyDiscoverableCredential): string;
28
+ /**
29
+ * Serialize a credential to a JSON string
30
+ * @param credential Credential
31
+ * @returns { id: Credential ID; data: JSON Credential }
32
+ */
33
+ export declare function serializeCredential(credential: PasskeyDiscoverableCredential): string;
34
+ /**
35
+ * Deserialize a credential from a JSON string
36
+ * @param data JSON string
37
+ * @returns Credential
38
+ */
39
+ export declare function deserializeCredential(data: string): PasskeyDiscoverableCredential;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getRepositoryId = getRepositoryId;
7
+ exports.serializeCredential = serializeCredential;
8
+ exports.deserializeCredential = deserializeCredential;
9
+ const encode_utils_1 = __importDefault(require("../libs/encode-utils"));
10
+ const webauthn_model_1 = require("../webauthn/webauthn-model");
11
+ const webauthn_model_json_1 = require("../webauthn/webauthn-model-json");
12
+ /**
13
+ * Get the ID of a credential
14
+ * @param credential Credential
15
+ */
16
+ function getRepositoryId(credential) {
17
+ return encode_utils_1.default.encodeBase64Url(credential.publicKeyCredentialDescriptor.id);
18
+ }
19
+ /**
20
+ * Serialize a credential to a JSON string
21
+ * @param credential Credential
22
+ * @returns { id: Credential ID; data: JSON Credential }
23
+ */
24
+ function serializeCredential(credential) {
25
+ const serialized = {
26
+ publicKeyCredentialDescriptor: (0, webauthn_model_json_1.toPublicKeyCredentialDescriptorJSON)(credential.publicKeyCredentialDescriptor),
27
+ publicKeyCredentialSource: (0, webauthn_model_1.toPublickeyCredentialSourceJSON)(credential.publicKeyCredentialSource),
28
+ authenticatorData: encode_utils_1.default.encodeBase64Url((0, webauthn_model_1.packAuthenticatorData)(credential.authenticatorData)),
29
+ user: (0, webauthn_model_json_1.toPublicKeyCredentialUserEntityJSON)(credential.user),
30
+ };
31
+ return JSON.stringify(serialized, null, 2);
32
+ }
33
+ /**
34
+ * Deserialize a credential from a JSON string
35
+ * @param data JSON string
36
+ * @returns Credential
37
+ */
38
+ function deserializeCredential(data) {
39
+ const serialized = JSON.parse(data);
40
+ return {
41
+ publicKeyCredentialDescriptor: (0, webauthn_model_json_1.parsePublicKeyCredentialDescriptorFromJSON)(serialized.publicKeyCredentialDescriptor),
42
+ publicKeyCredentialSource: (0, webauthn_model_1.parsePublicKeyCredentialSourceFromJSON)(serialized.publicKeyCredentialSource),
43
+ authenticatorData: (0, webauthn_model_1.unpackAuthenticatorData)(encode_utils_1.default.decodeBase64Url(serialized.authenticatorData)),
44
+ user: (0, webauthn_model_json_1.parsePublicKeyCredentialUserEntityFromJSON)(serialized.user),
45
+ };
46
+ }
@@ -0,0 +1,3 @@
1
+ export declare const WebAuthnEmulatorGet = "webAuthnEmulatorGet";
2
+ export declare const WebAuthnEmulatorCreate = "webAuthnEmulatorCreate";
3
+ export declare const HookWebAuthnApis: string;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.HookWebAuthnApis = exports.WebAuthnEmulatorCreate = exports.WebAuthnEmulatorGet = void 0;
27
+ const Model = __importStar(require("../webauthn/webauthn-model-json"));
28
+ exports.WebAuthnEmulatorGet = "webAuthnEmulatorGet";
29
+ exports.WebAuthnEmulatorCreate = "webAuthnEmulatorCreate";
30
+ const webAuthnModelExports = Object.values(Model)
31
+ .map((m) => m.toString())
32
+ .join("\n ");
33
+ exports.HookWebAuthnApis = `
34
+ (function () {
35
+ ${webAuthnModelExports}
36
+
37
+ window.navigator.credentials.create = async (options) => {
38
+ if (!options.publicKey) return undefined;
39
+ const optionsJSON = toCreationOptionsJSON(options.publicKey);
40
+ const responseJSON = await window.${exports.WebAuthnEmulatorCreate}(optionsJSON);
41
+ return parseRegistrationResponseFromJSON(responseJSON);
42
+ }
43
+
44
+ window.navigator.credentials.get = async (options) => {
45
+ if (!options.publicKey) return undefined;
46
+ const optionsJSON = toRequestOptionsJSON(options.publicKey);
47
+ const responseJSON = await window.${exports.WebAuthnEmulatorGet}(optionsJSON);
48
+ return parseAuthenticationResponseFromJSON(responseJSON);
49
+ }
50
+ PublicKeyCredential.isConditionalMediationAvailable = async () => true;
51
+ })();
52
+ `;
@@ -0,0 +1,16 @@
1
+ import { type JsonWebKey, type KeyObject } from "node:crypto";
2
+ /** @see https://www.w3.org/TR/webauthn/#sctn-encoded-credPubKey-examples */
3
+ export declare abstract class CoseKey {
4
+ kty: number;
5
+ alg: number;
6
+ constructor(kty: number, alg: number);
7
+ abstract toBytes(): Uint8Array;
8
+ abstract toJwk(): JsonWebKey;
9
+ toKeyObject(): KeyObject;
10
+ static fromKeyObject(keyObject: KeyObject): CoseKey;
11
+ toDer(): Uint8Array;
12
+ static fromDer(der: Uint8Array): CoseKey;
13
+ equals(other: CoseKey): boolean;
14
+ static fromBytes(bytes: Uint8Array): CoseKey;
15
+ static fromJwk(jwk: JsonWebKey): CoseKey;
16
+ }