Finish browser sign-in by attempt id, and on returning to the tab

Heimdall's Discord callback issues a random completion code distinct from
the attempt id, but the vendored adapter required the two to be equal and
rejected every real return as a malformed witness, so no player could sign
in. Re-vendored from Heimdall e8e2832, which completes by attempt id and
never reads the completion code; the test fixture issues a distinct code as
the server does.

A player who finishes Discord elsewhere and switches back to this tab never
reloads it, so the load-time resume never ran. The page now reruns the same
resume when it becomes visible with an attempt in flight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-23 20:51:20 +02:00
commit e42e1c1b31
4 changed files with 90 additions and 58 deletions

View file

@ -19,12 +19,14 @@ afterEach(() => {
restoreGlobal("window", originalGlobals.window);
});
test("browser return parser accepts only a matching completion witness", () => {
test("browser return parser completes by attempt id and never reads the completion code", () => {
const handle = "d0a9c1e7-89ac-46f9-8c85-c2484ed18f76";
assert.deepEqual(readHeimdallBrowserReturn(returnUrl(handle), "ghostlight"), { status: "success", handle });
assert.equal(readHeimdallBrowserReturn("https://yggdrasil.gamecult.org/ghostlight/", "ghostlight"), undefined);
assert.equal(readHeimdallBrowserReturn(returnUrl(handle), "another-app")?.status, "error");
assert.equal(readHeimdallBrowserReturn(returnUrl(handle, "different"), "ghostlight")?.status, "error");
assert.deepEqual(readHeimdallBrowserReturn(returnUrl(handle, "secret-redeem-code"), "ghostlight"), { status: "success", handle });
assert.ok(!JSON.stringify(readHeimdallBrowserReturn(returnUrl(handle, "secret-redeem-code"), "ghostlight")).includes("secret-redeem-code"));
assert.equal(readHeimdallBrowserReturn(returnUrl("", "secret-redeem-code"), "ghostlight")?.status, "error");
});
test("fresh browser context redeems the URL witness and scrubs it", async () => {
@ -76,7 +78,9 @@ function restoreGlobal(name, value) {
else Object.defineProperty(globalThis, name, { configurable: true, value });
}
function returnUrl(attemptId, completionCode = attemptId) {
// Heimdall issues a random completion code distinct from the attempt id, as
// the real callback does; the fixture must not restate the old equality.
function returnUrl(attemptId, completionCode = `code-for-${attemptId}`) {
const parameters = new URLSearchParams({
heimdall_status: "success",
heimdall_provider: "discord",