feat(auth): add local login and CSRF-protected sessions
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { test, expect } from "vitest";
|
||||
import { test, expect, vi } from "vitest";
|
||||
import Fastify from "fastify";
|
||||
import { authPreHandler, getPrincipal } from "../src/auth/auth.js";
|
||||
import { authenticateSession, authPreHandler, getPrincipal } from "../src/auth/auth.js";
|
||||
import { chmodSync, mkdtempSync, readFileSync, rmSync, statSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
@@ -107,6 +107,86 @@ test("upstream mode rejects legacy client identity headers without proxy princip
|
||||
}
|
||||
});
|
||||
|
||||
test("the session boundary exposes only exact health and authentication protocol paths", async () => {
|
||||
const app = Fastify();
|
||||
app.addHook("preHandler", authenticateSession({
|
||||
mode: "local",
|
||||
authentication: {
|
||||
current: () => ({
|
||||
sourcePath: "/private/auth.yaml",
|
||||
revision: "a".repeat(64),
|
||||
value: {
|
||||
version: 1,
|
||||
mode: "local",
|
||||
publicUrl: "http://127.0.0.1:8787",
|
||||
session: {
|
||||
regularTtlSeconds: 43_200, regularIdleSeconds: 7_200,
|
||||
rememberTtlSeconds: 2_592_000, rememberIdleSeconds: 604_800, oidcTtlSeconds: 28_800,
|
||||
},
|
||||
local: { usersFile: "users.yaml" },
|
||||
},
|
||||
}),
|
||||
},
|
||||
sessionStore: { resolve: async () => undefined } as any,
|
||||
}));
|
||||
app.get("/health", async () => ({ ok: true }));
|
||||
app.get("/auth/config", async () => ({ mode: "local" }));
|
||||
app.get("/healthz", async () => ({ ok: true }));
|
||||
app.get("/auth/configured", async () => ({ mode: "local" }));
|
||||
|
||||
expect((await app.inject({ method: "GET", url: "/health?probe=1" })).statusCode).toBe(200);
|
||||
expect((await app.inject({ method: "GET", url: "/auth/config?ui=1" })).statusCode).toBe(200);
|
||||
expect((await app.inject({ method: "GET", url: "/healthz" })).statusCode).toBe(401);
|
||||
expect((await app.inject({ method: "GET", url: "/auth/configured" })).statusCode).toBe(401);
|
||||
});
|
||||
|
||||
test("the session boundary touches a valid cookie session through the bounded Task 7 store operation", async () => {
|
||||
const sessions = {
|
||||
resolve: vi.fn(async () => ({
|
||||
version: 1,
|
||||
issuer: "local",
|
||||
subject: "user-1",
|
||||
method: "local",
|
||||
roles: ["user"],
|
||||
permissions: ["session.use"],
|
||||
userAuthRevision: 1,
|
||||
authConfigRevision: "b".repeat(64),
|
||||
remembered: false,
|
||||
createdAt: "2026-08-16T00:00:00.000Z",
|
||||
lastSeenAt: "2026-08-16T00:00:00.000Z",
|
||||
idleExpiresAt: "2026-08-16T02:00:00.000Z",
|
||||
absoluteExpiresAt: "2026-08-16T12:00:00.000Z",
|
||||
})),
|
||||
touch: vi.fn(async () => {}),
|
||||
};
|
||||
const app = Fastify();
|
||||
app.addHook("preHandler", authenticateSession({
|
||||
mode: "local",
|
||||
authentication: {
|
||||
current: () => ({
|
||||
sourcePath: "/private/auth.yaml",
|
||||
revision: "b".repeat(64),
|
||||
value: {
|
||||
version: 1,
|
||||
mode: "local",
|
||||
publicUrl: "http://127.0.0.1:8787",
|
||||
session: {
|
||||
regularTtlSeconds: 43_200, regularIdleSeconds: 7_200,
|
||||
rememberTtlSeconds: 2_592_000, rememberIdleSeconds: 604_800, oidcTtlSeconds: 28_800,
|
||||
},
|
||||
local: { usersFile: "users.yaml" },
|
||||
},
|
||||
}),
|
||||
},
|
||||
sessionStore: sessions as any,
|
||||
}));
|
||||
app.get("/private", async (request) => getPrincipal(request));
|
||||
|
||||
const token = "z".repeat(43);
|
||||
expect((await app.inject({ method: "GET", url: "/private", headers: { cookie: `thothii_session=${token}` } })).statusCode).toBe(200);
|
||||
expect(sessions.touch).toHaveBeenCalledWith(token);
|
||||
});
|
||||
|
||||
test("local identity expands tilde homes and restores private POSIX permissions", () => {
|
||||
expect(expandLocalHome("~/thoth-test", "/home/tester")).toBe("/home/tester/thoth-test");
|
||||
expect(expandLocalHome("~", "/home/tester")).toBe("/home/tester");
|
||||
|
||||
Reference in New Issue
Block a user