Files
WRNexusJS/packages/auth/test/passkey-runtime.test.ts

49 lines
1.9 KiB
TypeScript

import { expect, test, spyOn } from "bun:test";
import { readFileSync } from "node:fs";
import { Window } from "happy-dom";
test("passkey sign-in follows the server handoff, including cross-app destinations", async () => {
for (const redirect of [
"https://account.example.test/?sso_code=synthetic-code",
"/signed-in",
"javascript:alert(1)",
]) {
const window = new Window({ url: "https://sso.example.test/login" });
const assign = spyOn(window.location, "assign").mockImplementation(() => {});
try {
window.document.body.innerHTML = `<div data-auth-passkey><button>Sign in</button><p data-auth-status></p></div>`;
Object.defineProperty(window, "PublicKeyCredential", { value: class {} });
Object.defineProperty(window.navigator, "credentials", {
value: {
get: async () => ({
id: "synthetic-credential",
type: "public-key",
rawId: new Uint8Array([1]),
response: {
clientDataJSON: new Uint8Array([1]),
authenticatorData: new Uint8Array([2]),
signature: new Uint8Array([3]),
},
}),
},
});
window.fetch = (async (url: string) =>
Response.json(
url.endsWith("/options")
? { ok: true, key: "test-key", options: { challenge: "AQID" } }
: { ok: true, redirect },
)) as any;
window.eval(readFileSync(new URL("../assets/client/auth.js", import.meta.url), "utf8"));
await (window as any).WRNexusAuth.authenticatePasskey(window.document.querySelector("div"));
if (redirect.startsWith("javascript:")) {
expect(assign).not.toHaveBeenCalled();
} else {
expect(assign).toHaveBeenCalledWith(new URL(redirect, window.location.href).href);
}
} finally {
assign.mockRestore();
await window.happyDOM.close();
}
}
});