@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.
- package/LICENSE +201 -0
- package/README.md +167 -0
- package/bin/generate-passkey +2 -0
- package/dist/src/generate-passkey/cli.d.ts +2 -0
- package/dist/src/generate-passkey/cli.d.ts.map +1 -0
- package/dist/src/generate-passkey/cli.js +32 -0
- package/dist/src/generate-passkey/cli.js.map +1 -0
- package/dist/src/generate-passkey/generateTestPasskey.test.d.ts +2 -0
- package/dist/src/generate-passkey/generateTestPasskey.test.d.ts.map +1 -0
- package/dist/src/generate-passkey/generateTestPasskey.test.js +143 -0
- package/dist/src/generate-passkey/generateTestPasskey.test.js.map +1 -0
- package/dist/src/generate-passkey/index.d.ts +10 -0
- package/dist/src/generate-passkey/index.d.ts.map +1 -0
- package/dist/src/generate-passkey/index.js +158 -0
- package/dist/src/generate-passkey/index.js.map +1 -0
- package/dist/src/generate-passkey/test-cli.d.ts +2 -0
- package/dist/src/generate-passkey/test-cli.d.ts.map +1 -0
- package/dist/src/generate-passkey/test-cli.js +31 -0
- package/dist/src/generate-passkey/test-cli.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/passkey-util.d.ts +19 -0
- package/dist/src/passkey-util.d.ts.map +1 -0
- package/dist/src/passkey-util.js +58 -0
- package/dist/src/passkey-util.js.map +1 -0
- package/dist/src/scripts/client.d.ts +2 -0
- package/dist/src/scripts/client.d.ts.map +1 -0
- package/dist/src/scripts/client.js +97 -0
- package/dist/src/scripts/client.js.map +1 -0
- package/dist/src/scripts/server.d.ts +2 -0
- package/dist/src/scripts/server.d.ts.map +1 -0
- package/dist/src/scripts/server.js +224 -0
- package/dist/src/scripts/server.js.map +1 -0
- package/dist/src/scripts/testpasskey.d.ts +10 -0
- package/dist/src/scripts/testpasskey.d.ts.map +1 -0
- package/dist/src/scripts/testpasskey.js +88 -0
- package/dist/src/scripts/testpasskey.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +50 -0
- package/playwright-report/index.html +85 -0
- package/playwright.config.ts +80 -0
- package/src/generate-passkey/cli.ts +33 -0
- package/src/generate-passkey/generateTestPasskey.test.ts +165 -0
- package/src/generate-passkey/index.ts +228 -0
- package/src/generate-passkey/test-cli.ts +32 -0
- package/src/scripts/client.ts +136 -0
- package/src/scripts/server.ts +301 -0
- package/src/scripts/testpasskey.ts +87 -0
- package/test-passkey.js +87 -0
- package/test-passkey.ts +87 -0
- package/test-results/.last-run.json +4 -0
- package/tests/passkey.spec.ts +29 -0
- package/tsconfig.json +52 -0
- package/tsconfig.tsbuildinfo +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/scripts/server.ts"],"names":[],"mappings":""}
|