diff --git a/src/backend-handoff.ts b/src/backend-handoff.ts index e6cdacc..1f624e9 100644 --- a/src/backend-handoff.ts +++ b/src/backend-handoff.ts @@ -44,10 +44,10 @@ export async function deliverBackendHandoff(callbackUrl: string, payload: Backen body: JSON.stringify(payload), }); + // The status alone: the app's answer body can quote the handoff, which + // carries tokens, and whatever catches this may record or print it. if (!response.ok) { - const body = await response.text(); - throw new Error( - `Backend handoff delivery failed (status ${response.status}): ${body || "empty response"}` - ); + await response.body?.cancel(); + throw new Error(`Backend handoff delivery failed (status ${response.status}).`); } } diff --git a/tests/app.test.ts b/tests/app.test.ts index 374a3f4..2550d94 100644 --- a/tests/app.test.ts +++ b/tests/app.test.ts @@ -1,6 +1,7 @@ import { afterEach, describe, expect, it } from "vitest"; import { type FastifyInstance } from "fastify"; import { buildApp } from "../src/app.js"; +import { deliverBackendHandoff, type BackendHandoffPayload } from "../src/backend-handoff.js"; import { type HeimdallConfig, loadConfig } from "../src/config.js"; import { entitlementFacts, identityFacts } from "../src/facts.js"; import { createOAuthRuntimeRegistry, type OAuthProviderRuntime } from "../src/oauth.js"; @@ -1588,3 +1589,28 @@ describe("the failed-callback audit event for a provider's HTTP refusal", () => expect(failed?.eventPayloadJson.providerStatus).toBeNull(); }); }); + +describe("a backend handoff the app refuses", () => { + it("fails by status alone, never with the app's answer body", async () => { + globalThis.fetch = async () => new Response('{"error":"rejected","echo":"CANARYhandoff"}', { status: 500 }); + const failure = await deliverBackendHandoff("https://bifrost.gamecult.org/auth/heimdall/callback", { + source: "heimdall", + kind: "oauth_result", + handoffKind: "backend_callback", + attemptId: "attempt-1", + status: "error", + provider: "discord", + appSlug: "bifrost", + returnTo: "https://bifrost.gamecult.org/", + connection: null, + error: "oauth_callback_failed", + } as BackendHandoffPayload).then( + () => undefined, + (error: unknown) => error + ); + + expect(failure).toBeInstanceOf(Error); + expect((failure as Error).message).toBe("Backend handoff delivery failed (status 500)."); + expect(JSON.stringify(failure) + String(failure)).not.toContain("CANARY"); + }); +});