Exosphere is a set of small, modular, self-hostable community tools built on the AT Protocol.
app.exosphere.site
1import { createMiddleware } from "hono/factory";
2import { getCookie, deleteCookie } from "hono/cookie";
3import { getOAuthClient } from "./client.ts";
4import type { OAuthSession } from "@atproto/oauth-client-node";
5
6/** Hono env type — augments context with the authenticated user's DID */
7export type AuthEnv = {
8 Variables: {
9 did: string;
10 session: OAuthSession;
11 };
12};
13
14/**
15 * Middleware that requires authentication.
16 * Returns 401 if no valid session. Sets `c.var.did` and `c.var.session`.
17 */
18export const requireAuth = createMiddleware<AuthEnv>(async (c, next) => {
19 const did = getCookie(c, "sid");
20 if (!did) {
21 return c.json({ error: "Unauthorized" }, 401);
22 }
23
24 try {
25 const client = await getOAuthClient();
26 const session = await client.restore(did);
27 c.set("did", session.did);
28 c.set("session", session);
29 await next();
30 } catch {
31 deleteCookie(c, "sid", { path: "/" });
32 return c.json({ error: "Session expired" }, 401);
33 }
34});
35
36/**
37 * Middleware that optionally attaches auth info.
38 * Does not block unauthenticated requests.
39 */
40export const optionalAuth = createMiddleware<AuthEnv>(async (c, next) => {
41 const did = getCookie(c, "sid");
42 if (did) {
43 try {
44 const client = await getOAuthClient();
45 const session = await client.restore(did);
46 c.set("did", session.did);
47 c.set("session", session);
48 } catch {
49 deleteCookie(c, "sid", { path: "/" });
50 }
51 }
52 await next();
53});