Skip to content
File

Blob: tests/worker/routes/public-auth-and-invites.test.ts

typescript92 lines
1import { describe, expect, it } from "vitest";
2 
3import { authHeaders, createAuthenticatedSession, fetchJson, seedUser } from "../../helpers/runtime";
4import { registerWorkerRuntimeHooks } from "../../helpers/worker-hooks";
5 
6describe("worker public auth routes", () => {
7 registerWorkerRuntimeHooks();
8 
9 it("removes password login, invite acceptance, and private invite creation routes", async () => {
10 const user = await seedUser({
11 email: "removed-auth-routes@example.com",
12 slug: "removed-auth-routes",
13 });
14 const sessionId = await createAuthenticatedSession(user.id);
15 
16 const login = await fetchJson("/api/public/auth/login", {
17 method: "POST",
18 headers: {
19 "content-type": "application/json; charset=utf-8",
20 origin: "https://example.com",
21 },
22 body: JSON.stringify({}),
23 });
24 expect(login.status).toBe(404);
25 
26 const acceptInvite = await fetchJson("/api/public/auth/invite/accept", {
27 method: "POST",
28 headers: {
29 "content-type": "application/json; charset=utf-8",
30 origin: "https://example.com",
31 },
32 body: JSON.stringify({}),
33 });
34 expect(acceptInvite.status).toBe(404);
35 
36 const createInvite = await fetchJson("/api/private/invites", {
37 method: "POST",
38 headers: authHeaders(sessionId, {
39 "content-type": "application/json; charset=utf-8",
40 }),
41 body: JSON.stringify({}),
42 });
43 expect(createInvite.status).toBe(404);
44 });
45 
46 it("logs out idempotently with the session cookie transport", async () => {
47 const user = await seedUser({
48 email: "cookie-logout@example.com",
49 slug: "cookie-logout",
50 });
51 const sessionId = await createAuthenticatedSession(user.id);
52 
53 const authenticatedLogout = await fetchJson("/api/public/auth/logout", {
54 method: "POST",
55 headers: authHeaders(sessionId),
56 });
57 expect(authenticatedLogout.status).toBe(204);
58 expect(authenticatedLogout.response.headers.get("set-cookie")).toContain("__Host-anvil_session=");
59 
60 const me = await fetchJson("/api/private/me", {
61 headers: authHeaders(sessionId),
62 });
63 expect(me.status).toBe(403);
64 expect(me.body).toMatchObject({
65 error: {
66 code: "invalid_session",
67 },
68 });
69 
70 const anonymousLogout = await fetchJson("/api/public/auth/logout", {
71 method: "POST",
72 headers: {
73 origin: "https://example.com",
74 },
75 });
76 expect(anonymousLogout.status).toBe(204);
77 });
78 
79 it("blocks cookie-bound logout without same-origin evidence", async () => {
80 const result = await fetchJson("/api/public/auth/logout", {
81 method: "POST",
82 });
83 
84 expect(result.status).toBe(403);
85 expect(result.body).toMatchObject({
86 error: {
87 code: "cross_origin_blocked",
88 },
89 });
90 });
91});