import { expect, test } from "bun:test"; import type { Context } from "@wrnexus/core"; import { createAuthEngine } from "../src/engine.ts"; import { setDefaultAuthEngine } from "../src/runtime.ts"; import { MemoryAuthStore } from "../src/stores/memory.ts"; import { POST as requestPasswordReset } from "../src/routes/api/password-request.ts"; import { GET as listSessions } from "../src/routes/api/sessions.ts"; import { POST as passkeyLoginOptions } from "../src/routes/api/passkeys-login-options.ts"; function context(request: Request): Context { const values = new Map(); return { req: request, // Deliberately use unrelated values. A route-specific package entry must // not infer its endpoint from ctx.url, ctx.req.url, params, or locals. url: new URL("https://example.test/__wrnexus/rewritten"), params: {}, locals: {}, lang: "en", t: (key: string) => key, ip: "127.0.0.1", user: null, cookies: { get: (name: string) => (name === "wrn-csrf" ? "route-csrf-token" : undefined), } as Context["cookies"], localStorage: {} as Context["localStorage"], session: { id: () => "route-test-session", get: (key: string) => values.get(key) as T | undefined, getAll: () => Object.fromEntries(values), set: (key: string, value: unknown) => { values.set(key, value); }, delete: (key: string) => { values.delete(key); }, regenerate: () => {}, clear: () => { values.clear(); }, }, } as Context; } test("route-specific password recovery entry cannot fall through to Not Found", async () => { setDefaultAuthEngine( createAuthEngine({ store: new MemoryAuthStore(), secret: "route-specific-entry-secret-longer-than-thirty-two-characters", }), ); const request = new Request("https://example.test/completely/unrelated", { method: "POST", headers: { "content-type": "application/json", "x-csrf-token": "route-csrf-token", }, body: JSON.stringify({ identifier: "missing@example.test" }), }); const response = await requestPasswordReset(context(request)); expect(response.status).toBe(200); expect(await response.json()).toEqual({ ok: true }); }); test("package auth routes reject unsafe requests without CSRF verification", async () => { const request = new Request("https://example.test/api/auth/password/request", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ identifier: "missing@example.test" }), }); const response = await requestPasswordReset(context(request)); expect(response.status).toBe(403); expect(await response.json()).toMatchObject({ ok: false, error: "Invalid CSRF token" }); }); test("safe package auth routes do not require a CSRF token", async () => { const engine = createAuthEngine({ store: new MemoryAuthStore(), secret: "safe-route-secret-that-is-longer-than-thirty-two-characters", }); const registered = await engine.register({ email: "sessions@example.test", password: "StrongPassword123", }); setDefaultAuthEngine(engine); const ctx = context(new Request("https://example.test/api/auth/sessions", { method: "GET" })); ctx.user = registered.user!; ctx.locals.authUser = registered.user!; const response = await listSessions(ctx); expect(response.status).toBe(200); expect(await response.json()).toMatchObject({ ok: true, sessions: [] }); }); test("passkey routes return a controlled response when no provider is configured", async () => { setDefaultAuthEngine( createAuthEngine({ store: new MemoryAuthStore(), secret: "missing-passkey-provider-secret-longer-than-thirty-two-characters", }), ); const request = new Request("https://example.test/api/auth/passkeys/login/options", { method: "POST", headers: { "content-type": "application/json", "x-csrf-token": "route-csrf-token", }, body: JSON.stringify({}), }); const response = await passkeyLoginOptions(context(request)); expect(response.status).toBe(503); expect(await response.json()).toMatchObject({ ok: false, code: "passkey-provider-not-configured", }); });