add passkey support
This commit is contained in:
+4
-1
@@ -42,7 +42,7 @@ async function startServer() {
|
||||
.slice(2)}.db`,
|
||||
);
|
||||
const port = 20000 + Math.floor(Math.random() * 30000);
|
||||
const baseURL = `http://127.0.0.1:${port}`;
|
||||
const baseURL = `http://localhost:${port}`;
|
||||
|
||||
const child = spawn(
|
||||
path.resolve(__dirname, "..", "target", "debug", "sustenance"),
|
||||
@@ -53,6 +53,9 @@ async function startServer() {
|
||||
DATABASE_PATH: dbPath,
|
||||
REGISTRATION_MODE: "open",
|
||||
BIND_ADDRESS: `127.0.0.1:${port}`,
|
||||
PUBLIC_BASE_URL: baseURL,
|
||||
// WebAuthn requires a valid domain for the RP ID; localhost is allowed.
|
||||
RP_ID: "localhost",
|
||||
// Point SEED_CONFIG at a nonexistent file so no default user is created.
|
||||
SEED_CONFIG: path.join(os.tmpdir(), "sustenance-e2e-no-seed.json"),
|
||||
},
|
||||
|
||||
Generated
+17
-1
@@ -8,7 +8,8 @@
|
||||
"name": "sustenance-e2e",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.45.0"
|
||||
"@playwright/test": "^1.45.0",
|
||||
"@types/node": "^26.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
@@ -26,6 +27,15 @@
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz",
|
||||
"integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~8.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@@ -69,6 +79,12 @@
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
||||
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@
|
||||
"test:headed": "playwright test --headed"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.45.0"
|
||||
"@playwright/test": "^1.45.0",
|
||||
"@types/node": "^26.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import { test } from "../fixtures";
|
||||
import { registerAndLogin } from "../helpers";
|
||||
|
||||
/**
|
||||
* Enables a virtual WebAuthn authenticator on the given context so the browser
|
||||
* can complete passkey ceremonies without a real device.
|
||||
*/
|
||||
async function enableVirtualAuthenticator(context: any) {
|
||||
const cdp = await context.newCDPSession(context.pages()[0]);
|
||||
await cdp.send("WebAuthn.enable", { enableUI: false });
|
||||
await cdp.send("WebAuthn.addVirtualAuthenticator", {
|
||||
options: {
|
||||
protocol: "ctap2",
|
||||
transport: "internal",
|
||||
hasResidentKey: true,
|
||||
hasUserVerification: true,
|
||||
isUserVerified: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
test("a user can register a passkey and sign in with it", async ({ page, browser, server }) => {
|
||||
const context = await browser.newContext({ baseURL: server.baseURL });
|
||||
const p = await context.newPage();
|
||||
|
||||
await enableVirtualAuthenticator(context);
|
||||
|
||||
// Register with a password first.
|
||||
await registerAndLogin(p, "alice@example.com");
|
||||
|
||||
// Add a passkey from the account page.
|
||||
await p.goto("/account");
|
||||
await p.click("#add-passkey");
|
||||
await expect(p.locator(".passkey-row")).toHaveCount(1);
|
||||
|
||||
// Log out.
|
||||
await p.click('button:has-text("Sign out")');
|
||||
await expect(p).toHaveURL(/\/login/);
|
||||
|
||||
// Sign in with the passkey.
|
||||
await p.fill("#email", "alice@example.com");
|
||||
await p.click("#passkey-login");
|
||||
await expect(p).toHaveURL(/\/lists/);
|
||||
|
||||
await context.close();
|
||||
});
|
||||
Reference in New Issue
Block a user