WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1import type { OAuthSession } from "@atproto/oauth-client-node";
2import type { AppContext } from "./app-context.js";
3import type { CookieSession } from "./cookie-session-store.js";
4
5/**
6 * Result of restoring an OAuth session from a cookie token.
7 */
8export interface RestoredSession {
9 oauthSession: OAuthSession;
10 cookieSession: CookieSession;
11}
12
13/**
14 * Restore an OAuth session from a cookie token.
15 *
16 * Looks up the cookie token in the CookieSessionStore, then restores
17 * the OAuth session from the library's session store (with automatic
18 * token refresh).
19 *
20 * Returns both the OAuth session and cookie session if successful,
21 * allowing callers to access handle and other cookie metadata without
22 * redundant store queries.
23 *
24 * Returns null if the cookie session doesn't exist, is expired,
25 * or the OAuth session is not found (expected cases).
26 * Throws on unexpected errors (network failures, etc.) that should bubble up.
27 */
28export async function restoreOAuthSession(
29 ctx: AppContext,
30 cookieToken: string
31): Promise<RestoredSession | null> {
32 const cookieSession = ctx.cookieSessionStore.get(cookieToken);
33 if (!cookieSession) {
34 return null;
35 }
36
37 try {
38 // Restore OAuth session from library's session store
39 // This will automatically refresh tokens if needed
40 const oauthSession = await ctx.oauthClient.restore(cookieSession.did);
41 if (!oauthSession) {
42 return null;
43 }
44 return { oauthSession, cookieSession };
45 } catch (error) {
46 // Check if this is an expected "session not found" error
47 if (error instanceof Error && error.message.includes("not found")) {
48 return null;
49 }
50
51 // Unexpected error - log and re-throw
52 ctx.logger.error("Unexpected error restoring OAuth session", {
53 operation: "restoreOAuthSession",
54 did: cookieSession.did,
55 error: error instanceof Error ? error.message : String(error),
56 });
57 throw error;
58 }
59}