ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { createMiddleware } from "hono/factory";
2import { getCookie } from "hono/cookie";
3import { userSessionStore } from "../infrastructure/oauth";
4import { AuthenticationError, ERROR_MESSAGES } from "../errors";
5
6/**
7 * Authentication middleware for Hono
8 * Validates session cookies and adds user context to request
9 */
10export const authMiddleware = createMiddleware(async (c, next) => {
11 // Extract session from cookies
12 const sessionId =
13 getCookie(c, "atlast_session") || getCookie(c, "atlast_session_dev");
14
15 if (!sessionId) {
16 throw new AuthenticationError(ERROR_MESSAGES.NO_SESSION_COOKIE);
17 }
18
19 // Validate session with database
20 const userSession = await userSessionStore.get(sessionId);
21 if (!userSession) {
22 throw new AuthenticationError(ERROR_MESSAGES.INVALID_SESSION);
23 }
24
25 // Add session context to request
26 c.set("sessionId", sessionId);
27 c.set("did", userSession.did);
28
29 await next();
30});
31
32/**
33 * Extract session ID from cookies without validation
34 * Returns null if no session cookie exists
35 */
36export function extractSessionId(c: {
37 req: { header: (name: string) => string | undefined };
38}): string | null {
39 const cookieHeader = c.req.header("cookie");
40 if (!cookieHeader) return null;
41
42 // Simple cookie parsing (no external dependency needed for this case)
43 const cookies = cookieHeader.split(";").reduce(
44 (acc, cookie) => {
45 const [key, value] = cookie.trim().split("=");
46 if (key && value) {
47 acc[key] = value;
48 }
49 return acc;
50 },
51 {} as Record<string, string>,
52 );
53
54 return cookies.atlast_session || cookies.atlast_session_dev || null;
55}