feat(live): task 1.5.2 — cookie auth handshake
Authenticate WebSocket upgrade requests via Directus's /users/me: - src/live/auth.ts: createAuthClient factory; validate() forwards the raw Cookie: header to Directus, parses the user with zod, and returns AuthenticatedUser or null. Handles 401/403 (unauthorized), non-2xx (error), network failures, AbortError (timeout), null data (expired session), and missing data key (malformed Directus response). - src/live/server.ts: upgrade handler now calls authClient.validate() before completing the WS handshake; on null user, writes HTTP 401 and destroys the socket. LiveConnection gains user: AuthenticatedUser and cookieHeader: string (needed for per-subscription authz in task 1.5.3). authClient is an optional parameter so tests without auth still work. - src/main.ts: wires createAuthClient and passes it to createLiveServer. - test/live-auth.test.ts: 11 unit tests covering all validate() code paths including the empty-cookie fast-path, latency histogram observation, and distinction between unauthorized (401/expired) and error (malformed) results.
This commit is contained in:
+7
-2
@@ -19,6 +19,7 @@ import { createWriter } from './core/writer.js';
|
||||
import { createLiveServer, sendOutbound } from './live/server.js';
|
||||
import type { LiveServer, LiveConnection } from './live/server.js';
|
||||
import type { InboundMessage } from './live/protocol.js';
|
||||
import { createAuthClient } from './live/auth.js';
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Startup: validate config (fail fast on bad env), build logger
|
||||
@@ -131,9 +132,11 @@ async function main(): Promise<void> {
|
||||
return ackIds;
|
||||
};
|
||||
|
||||
// 10. Build the live WebSocket server (task 1.5.1).
|
||||
// 10. Build the live WebSocket server (task 1.5.2 adds auth).
|
||||
// The stub message handler replies with `error/not-implemented` until
|
||||
// tasks 1.5.2 and 1.5.3 wire in the real auth + registry handler.
|
||||
// task 1.5.3 wires in the real subscription-registry handler.
|
||||
const authClient = createAuthClient(config, logger, metrics);
|
||||
|
||||
const stubMessageHandler = async (
|
||||
conn: LiveConnection,
|
||||
_message: InboundMessage,
|
||||
@@ -151,6 +154,8 @@ async function main(): Promise<void> {
|
||||
logger,
|
||||
metrics,
|
||||
stubMessageHandler,
|
||||
undefined, // onClose: wired in task 1.5.3
|
||||
authClient,
|
||||
);
|
||||
await liveServer.start();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user