← back to Govarbitrage

apps/mobile/tests/auth-headers.test.mjs

50 lines

/**
 * Regression tests for lib/auth-headers.ts — the app's auth-header policy after
 * the Guideline 5.6 fix (TK-10279). Zero-dependency: Node's built-in test runner
 * with TS type-stripping (auth-headers.ts is a pure module, no native imports).
 *
 * Run: npm run test:unit
 *
 * What these lock in:
 *   • a fresh install (no Apple sign-in, no self-hosting creds) sends NO
 *     Authorization header — byte-identical to what a browser/curl sends, which
 *     is the whole point of the 5.6 fix (behavior can't vary by client).
 *   • the removed "token:" x-import-token secret path stays removed — a password
 *     that happens to start with "token:" is just a normal Basic password now.
 */
import { test } from "node:test";
import assert from "node:assert/strict";
import { authHeadersFor, buildBasicAuthHeader } from "../lib/auth-headers.ts";

test("fresh install → NO Authorization header (anonymous, identical to a browser)", () => {
  assert.deepEqual(authHeadersFor({}), {});
  assert.deepEqual(authHeadersFor({ appleToken: null, username: "", password: "" }), {});
  // A username with no password still sends nothing — nothing to authenticate.
  assert.deepEqual(authHeadersFor({ username: "admin", password: "" }), {});
});

test("Apple sign-in → Bearer, and it wins over any self-hosting creds", () => {
  assert.deepEqual(authHeadersFor({ appleToken: "jwt123" }), {
    Authorization: "Bearer jwt123",
  });
  assert.deepEqual(
    authHeadersFor({ appleToken: "jwt123", username: "u", password: "p" }),
    { Authorization: "Bearer jwt123" }
  );
});

test("self-hosting username+password → Basic", () => {
  assert.deepEqual(authHeadersFor({ username: "u", password: "p" }), {
    Authorization: buildBasicAuthHeader("u", "p"),
  });
  assert.equal(buildBasicAuthHeader("u", "p"), `Basic ${btoa("u:p")}`);
});

test("the 'token:' secret machine-token path is gone", () => {
  // Pre-fix, a password prefixed 'token:' became an x-import-token backdoor
  // header. Now it is treated as an ordinary Basic password — no special path.
  const headers = authHeadersFor({ username: "u", password: "token:SECRET" });
  assert.ok(!("x-import-token" in headers), "no x-import-token header is ever produced");
  assert.deepEqual(headers, { Authorization: buildBasicAuthHeader("u", "token:SECRET") });
});