@test2doc/playwright-passkey-gen 0.0.0

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 (57) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +167 -0
  3. package/bin/generate-passkey +2 -0
  4. package/dist/src/generate-passkey/cli.d.ts +2 -0
  5. package/dist/src/generate-passkey/cli.d.ts.map +1 -0
  6. package/dist/src/generate-passkey/cli.js +32 -0
  7. package/dist/src/generate-passkey/cli.js.map +1 -0
  8. package/dist/src/generate-passkey/generateTestPasskey.test.d.ts +2 -0
  9. package/dist/src/generate-passkey/generateTestPasskey.test.d.ts.map +1 -0
  10. package/dist/src/generate-passkey/generateTestPasskey.test.js +143 -0
  11. package/dist/src/generate-passkey/generateTestPasskey.test.js.map +1 -0
  12. package/dist/src/generate-passkey/index.d.ts +10 -0
  13. package/dist/src/generate-passkey/index.d.ts.map +1 -0
  14. package/dist/src/generate-passkey/index.js +158 -0
  15. package/dist/src/generate-passkey/index.js.map +1 -0
  16. package/dist/src/generate-passkey/test-cli.d.ts +2 -0
  17. package/dist/src/generate-passkey/test-cli.d.ts.map +1 -0
  18. package/dist/src/generate-passkey/test-cli.js +31 -0
  19. package/dist/src/generate-passkey/test-cli.js.map +1 -0
  20. package/dist/src/index.d.ts +2 -0
  21. package/dist/src/index.d.ts.map +1 -0
  22. package/dist/src/index.js +2 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/passkey-util.d.ts +19 -0
  25. package/dist/src/passkey-util.d.ts.map +1 -0
  26. package/dist/src/passkey-util.js +58 -0
  27. package/dist/src/passkey-util.js.map +1 -0
  28. package/dist/src/scripts/client.d.ts +2 -0
  29. package/dist/src/scripts/client.d.ts.map +1 -0
  30. package/dist/src/scripts/client.js +97 -0
  31. package/dist/src/scripts/client.js.map +1 -0
  32. package/dist/src/scripts/server.d.ts +2 -0
  33. package/dist/src/scripts/server.d.ts.map +1 -0
  34. package/dist/src/scripts/server.js +224 -0
  35. package/dist/src/scripts/server.js.map +1 -0
  36. package/dist/src/scripts/testpasskey.d.ts +10 -0
  37. package/dist/src/scripts/testpasskey.d.ts.map +1 -0
  38. package/dist/src/scripts/testpasskey.js +88 -0
  39. package/dist/src/scripts/testpasskey.js.map +1 -0
  40. package/dist/tsconfig.tsbuildinfo +1 -0
  41. package/package.json +50 -0
  42. package/playwright-report/index.html +85 -0
  43. package/playwright.config.ts +80 -0
  44. package/src/generate-passkey/cli.ts +33 -0
  45. package/src/generate-passkey/generateTestPasskey.test.ts +165 -0
  46. package/src/generate-passkey/index.ts +228 -0
  47. package/src/generate-passkey/test-cli.ts +32 -0
  48. package/src/scripts/client.ts +136 -0
  49. package/src/scripts/server.ts +301 -0
  50. package/src/scripts/testpasskey.ts +87 -0
  51. package/test-passkey.js +87 -0
  52. package/test-passkey.ts +87 -0
  53. package/test-results/.last-run.json +4 -0
  54. package/tests/passkey.spec.ts +29 -0
  55. package/tsconfig.json +52 -0
  56. package/tsconfig.tsbuildinfo +1 -0
  57. package/vitest.config.ts +8 -0
@@ -0,0 +1,158 @@
1
+ import { chromium } from "@playwright/test";
2
+ import { writeFileSync } from "fs";
3
+ import { join } from "path";
4
+ import { verifyRegistrationResponse } from "@simplewebauthn/server";
5
+ import { Command } from "commander";
6
+ import { fileURLToPath } from "url";
7
+ function isVirtualAuthenticatorCredential(cred) {
8
+ return (cred !== null &&
9
+ typeof cred === "object" &&
10
+ "credentialId" in cred &&
11
+ "privateKey" in cred &&
12
+ "userHandle" in cred &&
13
+ "signCount" in cred);
14
+ }
15
+ export async function generateTestPasskey(username, userId) {
16
+ const browser = await chromium.launch();
17
+ const context = await browser.newContext();
18
+ const page = await context.newPage();
19
+ await page.goto("http://localhost:5173/");
20
+ // Set up virtual authenticator
21
+ const client = await context.newCDPSession(page);
22
+ await client.send("WebAuthn.enable");
23
+ const result = await client.send("WebAuthn.addVirtualAuthenticator", {
24
+ options: {
25
+ protocol: "ctap2",
26
+ transport: "internal",
27
+ hasResidentKey: true,
28
+ hasUserVerification: true,
29
+ isUserVerified: true,
30
+ automaticPresenceSimulation: true,
31
+ },
32
+ });
33
+ const authenticatorId = result.authenticatorId;
34
+ // Generate a credential by simulating registration
35
+ const credentialResponse = await page.evaluate(async ({ userId, username }) => {
36
+ try {
37
+ const credential = await navigator.credentials.create({
38
+ publicKey: {
39
+ challenge: new Uint8Array(32),
40
+ rp: {
41
+ name: "Test App",
42
+ id: "localhost",
43
+ },
44
+ user: {
45
+ id: new TextEncoder().encode(userId),
46
+ name: username,
47
+ displayName: username,
48
+ },
49
+ pubKeyCredParams: [{ alg: -7, type: "public-key" }],
50
+ },
51
+ });
52
+ // Type guards
53
+ function isPublicKeyCredential(credential) {
54
+ return credential !== null && credential.type === "public-key";
55
+ }
56
+ function isAuthenticatorAttestationResponse(response) {
57
+ return "attestationObject" in response;
58
+ }
59
+ if (!isPublicKeyCredential(credential)) {
60
+ throw new Error("Failed to create public key credential");
61
+ }
62
+ if (!isAuthenticatorAttestationResponse(credential.response)) {
63
+ throw new Error("Response is not an attestation response");
64
+ }
65
+ return {
66
+ id: credential.id,
67
+ rawId: Array.from(new Uint8Array(credential.rawId)),
68
+ response: {
69
+ clientDataJSON: Array.from(new Uint8Array(credential.response.clientDataJSON)),
70
+ attestationObject: Array.from(new Uint8Array(credential.response.attestationObject)),
71
+ },
72
+ clientExtensionResults: {},
73
+ transports: ["internal"],
74
+ type: "public-key",
75
+ };
76
+ }
77
+ catch (err) {
78
+ throw new Error(`Credential creation failed: ${err}`);
79
+ }
80
+ }, { userId, username });
81
+ // Extract the credential from the virtual authenticator
82
+ const credentials = await client.send("WebAuthn.getCredentials", {
83
+ authenticatorId,
84
+ });
85
+ if (!credentials.credentials || credentials.credentials.length === 0) {
86
+ throw new Error("No credentials found in virtual authenticator");
87
+ }
88
+ const credential = credentials.credentials[0];
89
+ if (!isVirtualAuthenticatorCredential(credential)) {
90
+ throw new Error("Invalid credential structure from virtual authenticator");
91
+ }
92
+ const verification = await verifyRegistrationResponse({
93
+ response: {
94
+ id: credentialResponse.id,
95
+ rawId: Buffer.from(credentialResponse.rawId).toString("base64url"),
96
+ response: {
97
+ clientDataJSON: Buffer.from(credentialResponse.response.clientDataJSON).toString("base64url"),
98
+ attestationObject: Buffer.from(credentialResponse.response.attestationObject).toString("base64url"),
99
+ },
100
+ type: "public-key",
101
+ clientExtensionResults: {},
102
+ },
103
+ expectedChallenge: Buffer.from(new Uint8Array(32)).toString("base64url"), // the challenge you used
104
+ expectedOrigin: "http://localhost:5173",
105
+ expectedRPID: "localhost",
106
+ });
107
+ if (verification.verified && verification.registrationInfo) {
108
+ const testPasskey = {
109
+ username,
110
+ userId,
111
+ credentialId: Buffer.from(credential.credentialId, "base64").toString("base64"),
112
+ publicKey: Array.from(verification.registrationInfo.credential.publicKey),
113
+ privateKey: credential.privateKey,
114
+ credentialDbId: credentialResponse.id,
115
+ signCount: credential.signCount,
116
+ };
117
+ await browser.close();
118
+ return testPasskey;
119
+ }
120
+ throw new Error("Failed to verify registration response");
121
+ }
122
+ export async function main({ output = "test-passkey.ts", type = "ts", } = {}) {
123
+ const username = "testuser";
124
+ const userId = crypto.randomUUID();
125
+ console.log("Generating test passkey...");
126
+ console.log(`Username: ${username}`);
127
+ console.log(`User ID: ${userId}`);
128
+ const passkey = await generateTestPasskey(username, userId);
129
+ // Map type to file extension
130
+ const extensionMap = {
131
+ json: ".json",
132
+ js: ".js",
133
+ javascript: ".js",
134
+ ts: ".ts",
135
+ typescript: ".ts",
136
+ };
137
+ const ext = extensionMap[type] || ".ts";
138
+ output = output.replace(/\.\w+$/, "") + ext;
139
+ const outputPath = join(process.cwd(), output);
140
+ const stringifyPasskey = JSON.stringify(passkey, null, 2);
141
+ const content = type === "json"
142
+ ? stringifyPasskey
143
+ : `export const TESTPASSKEY = ${stringifyPasskey}`;
144
+ writeFileSync(outputPath, content);
145
+ console.log(`✓ Test passkey generated and saved to ${outputPath}`);
146
+ console.log("\nGenerated passkey:");
147
+ console.log(stringifyPasskey);
148
+ }
149
+ if (fileURLToPath(import.meta.url) === process.argv[1]) {
150
+ const program = new Command();
151
+ program
152
+ .option("-o, --output <path>", "output path for generated passkey", "test-passkey.ts")
153
+ .option("-t, --type <type>", "output file type (json, ts, js, typescript, javascript)", "ts")
154
+ .parse();
155
+ const opts = program.opts();
156
+ main(opts).catch(console.error);
157
+ }
158
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/generate-passkey/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-cli.d.ts","sourceRoot":"","sources":["../../../src/generate-passkey/test-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { spawn } from "child_process";
2
+ const server = spawn("pnpm", ["start"], { stdio: "inherit" });
3
+ const killServer = () => {
4
+ try {
5
+ if (server && !server.killed)
6
+ server.kill();
7
+ }
8
+ catch {
9
+ /* ignore */
10
+ }
11
+ };
12
+ ["exit", "SIGINT", "SIGTERM", "uncaughtException"].forEach((ev) => {
13
+ process.on(ev, () => {
14
+ killServer();
15
+ // for signals/uncaught exceptions exit with non-zero
16
+ if (ev !== "exit")
17
+ process.exit(1);
18
+ });
19
+ });
20
+ // run the local vitest via pnpm exec so it works in CI/Windows too
21
+ const tests = spawn("pnpm", ["exec", "vitest", "run"], { stdio: "inherit" });
22
+ tests.on("close", (code) => {
23
+ killServer();
24
+ process.exit(code ?? 0);
25
+ });
26
+ tests.on("error", (err) => {
27
+ killServer();
28
+ console.error(err);
29
+ process.exit(1);
30
+ });
31
+ //# sourceMappingURL=test-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-cli.js","sourceRoot":"","sources":["../../../src/generate-passkey/test-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAE7D,MAAM,UAAU,GAAG,GAAG,EAAE;IACtB,IAAI,CAAC;QACH,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC,CAEA;AAAA,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;IACjE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE;QAClB,UAAU,EAAE,CAAA;QACZ,qDAAqD;QACrD,IAAI,EAAE,KAAK,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,mEAAmE;AACnE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAE5E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;IACzB,UAAU,EAAE,CAAA;IACZ,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAA;AACzB,CAAC,CAAC,CAAA;AACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;IACxB,UAAU,EAAE,CAAA;IACZ,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from "./passkey-util.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from "./passkey-util.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA"}
@@ -0,0 +1,19 @@
1
+ import type { CDPSession, Page } from "@playwright/test";
2
+ import type { TestPasskey } from "./generate-passkey/index.js";
3
+ interface PasskeyAuthenticator {
4
+ client: CDPSession;
5
+ authenticatorId: string;
6
+ }
7
+ interface VirtualAuthenticatorOptions {
8
+ protocol: "ctap2" | "u2f";
9
+ transport: "usb" | "nfc" | "ble" | "cable" | "internal";
10
+ hasResidentKey?: boolean;
11
+ hasUserVerification?: boolean;
12
+ isUserVerified?: boolean;
13
+ automaticPresenceSimulation?: boolean;
14
+ }
15
+ export declare function enablePasskey(page: Page, options?: VirtualAuthenticatorOptions): Promise<PasskeyAuthenticator>;
16
+ export declare function addPasskeyCredential({ client, authenticatorId }: PasskeyAuthenticator, testPasskey: TestPasskey): Promise<void>;
17
+ export declare function simulateSuccessfulPasskeyInput({ client, authenticatorId }: PasskeyAuthenticator, operationTrigger: () => Promise<void>): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=passkey-util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-util.d.ts","sourceRoot":"","sources":["../../src/passkey-util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAE9D,UAAU,oBAAoB;IAC5B,MAAM,EAAE,UAAU,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;CACxB;AACD,UAAU,2BAA2B;IACnC,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAA;IACzB,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,CAAA;IACvD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,2BAOR,GACA,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED,wBAAsB,oBAAoB,CACxC,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,oBAAoB,EACjD,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,8BAA8B,CAClD,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,oBAAoB,EACjD,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,iBAiCtC"}
@@ -0,0 +1,58 @@
1
+ export async function enablePasskey(page, options = {
2
+ protocol: "ctap2",
3
+ transport: "internal",
4
+ hasResidentKey: true,
5
+ hasUserVerification: true,
6
+ isUserVerified: true,
7
+ automaticPresenceSimulation: true,
8
+ }) {
9
+ const client = await page.context().newCDPSession(page);
10
+ await client.send("WebAuthn.enable");
11
+ const result = await client.send("WebAuthn.addVirtualAuthenticator", {
12
+ options,
13
+ });
14
+ const authenticatorId = result.authenticatorId;
15
+ return { client, authenticatorId };
16
+ }
17
+ export async function addPasskeyCredential({ client, authenticatorId }, testPasskey) {
18
+ await client.send("WebAuthn.addCredential", {
19
+ authenticatorId,
20
+ credential: {
21
+ credentialId: Buffer.from(testPasskey.credentialId, "base64url").toString("base64"),
22
+ isResidentCredential: true,
23
+ rpId: "localhost",
24
+ privateKey: testPasskey.privateKey,
25
+ userHandle: Buffer.from(testPasskey.username, "utf8").toString("base64"),
26
+ signCount: testPasskey.signCount,
27
+ },
28
+ });
29
+ }
30
+ export async function simulateSuccessfulPasskeyInput({ client, authenticatorId }, operationTrigger) {
31
+ // initialize event listeners to wait for a successful passkey input event
32
+ const operationCompleted = new Promise((resolve) => {
33
+ client.on("WebAuthn.credentialAdded", () => resolve());
34
+ client.on("WebAuthn.credentialAsserted", () => resolve());
35
+ });
36
+ // set isUserVerified option to true
37
+ // (so that subsequent passkey operations will be successful)
38
+ await client.send("WebAuthn.setUserVerified", {
39
+ authenticatorId: authenticatorId,
40
+ isUserVerified: true,
41
+ });
42
+ // set automaticPresenceSimulation option to true
43
+ // (so that the virtual authenticator will respond to the next passkey prompt)
44
+ await client.send("WebAuthn.setAutomaticPresenceSimulation", {
45
+ authenticatorId: authenticatorId,
46
+ enabled: true,
47
+ });
48
+ // perform a user action that triggers passkey prompt
49
+ await operationTrigger();
50
+ // wait to receive the event that the passkey was successfully registered or verified
51
+ await operationCompleted;
52
+ // set automaticPresenceSimulation option back to false
53
+ await client.send("WebAuthn.setAutomaticPresenceSimulation", {
54
+ authenticatorId,
55
+ enabled: false,
56
+ });
57
+ }
58
+ //# sourceMappingURL=passkey-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-util.js","sourceRoot":"","sources":["../../src/passkey-util.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAU,EACV,UAAuC;IACrC,QAAQ,EAAE,OAAO;IACjB,SAAS,EAAE,UAAU;IACrB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,IAAI;IACzB,cAAc,EAAE,IAAI;IACpB,2BAA2B,EAAE,IAAI;CAClC;IAED,MAAM,MAAM,GAAe,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IACnE,MAAM,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAEpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE;QACnE,OAAO;KACR,CAAC,CAAA;IACF,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAA;IAE9C,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAA;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAE,MAAM,EAAE,eAAe,EAAwB,EACjD,WAAwB;IAExB,MAAM,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE;QAC1C,eAAe;QACf,UAAU,EAAE;YACV,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,QAAQ,CACvE,QAAQ,CACT;YACD,oBAAoB,EAAE,IAAI;YAC1B,IAAI,EAAE,WAAW;YACjB,UAAU,EAAE,WAAW,CAAC,UAAU;YAClC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACxE,SAAS,EAAE,WAAW,CAAC,SAAS;SACjC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,EAAE,MAAM,EAAE,eAAe,EAAwB,EACjD,gBAAqC;IAErC,0EAA0E;IAC1E,MAAM,kBAAkB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACvD,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;QACtD,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,oCAAoC;IACpC,6DAA6D;IAC7D,MAAM,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;QAC5C,eAAe,EAAE,eAAe;QAChC,cAAc,EAAE,IAAI;KACrB,CAAC,CAAA;IAEF,iDAAiD;IACjD,8EAA8E;IAC9E,MAAM,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE;QAC3D,eAAe,EAAE,eAAe;QAChC,OAAO,EAAE,IAAI;KACd,CAAC,CAAA;IAEF,qDAAqD;IACrD,MAAM,gBAAgB,EAAE,CAAA;IAExB,qFAAqF;IACrF,MAAM,kBAAkB,CAAA;IAExB,uDAAuD;IACvD,MAAM,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE;QAC3D,eAAe;QACf,OAAO,EAAE,KAAK;KACf,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const clientScript: string;
2
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/scripts/client.ts"],"names":[],"mappings":"AAkIA,eAAO,MAAM,YAAY,EAAE,MAK1B,CAAA"}
@@ -0,0 +1,97 @@
1
+ // client.ts
2
+ function base64urlToBuffer(base64url) {
3
+ // Convert base64url to base64
4
+ const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
5
+ const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), "=");
6
+ // Decode base64 to binary string
7
+ const binary = atob(padded);
8
+ // Convert to ArrayBuffer
9
+ const bytes = new Uint8Array(binary.length);
10
+ for (let i = 0; i < binary.length; i++) {
11
+ bytes[i] = binary.charCodeAt(i);
12
+ }
13
+ return bytes.buffer;
14
+ }
15
+ function arrayBufferToBase64url(buffer) {
16
+ const bytes = new Uint8Array(buffer);
17
+ let binary = "";
18
+ for (const c of bytes) {
19
+ binary += String.fromCharCode(c);
20
+ }
21
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
22
+ }
23
+ function updateStatus(statusDiv, message, type) {
24
+ console.log(message);
25
+ statusDiv.textContent = message;
26
+ statusDiv.className = `status ${type}`;
27
+ }
28
+ async function testAuthentication() {
29
+ const statusDiv = document.getElementById("status");
30
+ if (!statusDiv) {
31
+ throw new Error("Status div not found");
32
+ }
33
+ try {
34
+ updateStatus(statusDiv, "Starting authentication...", "loading");
35
+ const optionsResponse = await fetch("/authenticate/start", {
36
+ method: "POST",
37
+ headers: { "Content-Type": "application/json" },
38
+ });
39
+ if (!optionsResponse.ok) {
40
+ throw new Error("Failed to get authentication options");
41
+ }
42
+ const options = await optionsResponse.json();
43
+ updateStatus(statusDiv, "Got authentication options", "loading");
44
+ const assertion = await navigator.credentials.get({
45
+ publicKey: {
46
+ challenge: base64urlToBuffer(options.challenge),
47
+ rpId: options.rpId,
48
+ userVerification: "preferred",
49
+ allowCredentials: options.allowCredentials,
50
+ },
51
+ });
52
+ if (!assertion) {
53
+ throw new Error("User cancelled authentication");
54
+ }
55
+ function isPublicKeyCredential(credential) {
56
+ return credential !== null && credential.type === "public-key";
57
+ }
58
+ function isAuthenticatorAssertionResponse(response) {
59
+ return "signature" in response && "authenticatorData" in response;
60
+ }
61
+ if (!isPublicKeyCredential(assertion)) {
62
+ throw new Error("No valid PublicKeyCredential returned");
63
+ }
64
+ if (!isAuthenticatorAssertionResponse(assertion.response)) {
65
+ throw new Error("Response is not an assertion response");
66
+ }
67
+ updateStatus(statusDiv, "Got credential from authenticator", "loading");
68
+ const response = await fetch("/authenticate/finish", {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({
72
+ credentialId: assertion.id,
73
+ clientDataJSON: arrayBufferToBase64url(assertion.response.clientDataJSON),
74
+ authenticatorData: arrayBufferToBase64url(assertion.response.authenticatorData),
75
+ signature: arrayBufferToBase64url(assertion.response.signature),
76
+ // signCount: assertion.response.signCount,
77
+ }),
78
+ });
79
+ if (!response.ok) {
80
+ const error = await response.json();
81
+ throw new Error(error.error || "Authentication failed");
82
+ }
83
+ const result = await response.json();
84
+ updateStatus(statusDiv, `✓ Authentication successful! User ID: ${result.userId}`, "success");
85
+ }
86
+ catch (error) {
87
+ updateStatus(statusDiv, `✗ Error: ${error instanceof Error ? error.message : String(error)}`, "error");
88
+ console.error(error);
89
+ }
90
+ }
91
+ export const clientScript = `
92
+ ${base64urlToBuffer.toString()}
93
+ ${arrayBufferToBase64url.toString()}
94
+ ${updateStatus.toString()}
95
+ ${testAuthentication.toString()}
96
+ `;
97
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/scripts/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/scripts/server.ts"],"names":[],"mappings":""}