fix(auth): bind current local registry and CORS
This commit is contained in:
@@ -47,19 +47,30 @@ afterAll(async () => {
|
||||
test.each(stateChangingRoutes)(
|
||||
"$family $method $url rejects every production CSRF/session-boundary failure before downstream code",
|
||||
async ({ method, url }) => {
|
||||
const failures = [
|
||||
fixture.sessionHeaders({ "x-thothii-csrf": undefined }),
|
||||
fixture.sessionHeaders({ "x-thothii-csrf": "malformed" }),
|
||||
fixture.sessionHeaders({ origin: undefined }),
|
||||
fixture.sessionHeaders({ origin: "http://wrong.example.test" }),
|
||||
fixture.sessionHeaders({ "sec-fetch-site": "cross-site" }),
|
||||
const failures: Array<{ expectedStatus: number; headers: Record<string, string> }> = [
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": undefined }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": "malformed" }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": `${fixture.csrfToken}, ${fixture.csrfToken}` }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": "x".repeat(4097) }) },
|
||||
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: undefined }) },
|
||||
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: "thothii_session=not-a-token" }) },
|
||||
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: `${fixture.cookie}; ${fixture.cookie}` }) },
|
||||
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: `${fixture.cookie}; padding=${"x".repeat(4097)}` }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: undefined }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: "http://wrong.example.test" }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: `${localPublicUrl}, ${localPublicUrl}` }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: `${localPublicUrl}${"x".repeat(4097)}` }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "sec-fetch-site": "cross-site" }) },
|
||||
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "sec-fetch-site": "same-origin, same-origin" }) },
|
||||
];
|
||||
|
||||
for (const headers of failures) {
|
||||
for (const { expectedStatus, headers } of failures) {
|
||||
fixture.resetDownstreamHits();
|
||||
const response = await fixture.app.inject({ method, url, headers, payload: {} });
|
||||
expect(response.statusCode).toBe(403);
|
||||
expect(response.json()).toEqual({ code: "csrf_failed", error: "Request origin validation failed" });
|
||||
expect(response.statusCode).toBe(expectedStatus);
|
||||
expect(response.json()).toEqual(expectedStatus === 403
|
||||
? { code: "csrf_failed", error: "Request origin validation failed" }
|
||||
: { code: "authentication_required", error: "Authentication is required" });
|
||||
expect(fixture.downstreamHits()).toBe(0);
|
||||
}
|
||||
},
|
||||
@@ -78,3 +89,16 @@ test("a valid real local session cookie and derived CSRF token cross the same pr
|
||||
expect(fixture.downstreamHits()).toBe(1);
|
||||
expect(localPublicUrl).toBe("http://127.0.0.1:8787");
|
||||
});
|
||||
|
||||
test("a valid control may omit optional Fetch Metadata while retaining its exact Origin and CSRF pair", async () => {
|
||||
fixture.resetDownstreamHits();
|
||||
const response = await fixture.app.inject({
|
||||
method: "PUT",
|
||||
url: "/settings",
|
||||
headers: fixture.sessionHeaders({ "sec-fetch-site": undefined }),
|
||||
payload: {},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(fixture.downstreamHits()).toBe(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user