import type { AstroCookies } from 'astro' import type { NodeSavedSession, NodeSavedSessionStore, NodeSavedState, NodeSavedStateStore, } from '@atproto/oauth-client-node' // Cookie-based storage for OAuth state and sessions // All data is serialized into cookies for stateless operation export class CookieStateStore implements NodeSavedStateStore { constructor(private cookies: AstroCookies) {} async get(key: string): Promise { const cookieName = `oauth_state_${key}` const cookie = this.cookies.get(cookieName) if (!cookie?.value) return undefined try { const decoded = atob(cookie.value) return JSON.parse(decoded) as NodeSavedState } catch (err) { console.warn('Failed to decode OAuth state:', err) return undefined } } async set(key: string, val: NodeSavedState) { const cookieName = `oauth_state_${key}` const encoded = btoa(JSON.stringify(val)) this.cookies.set(cookieName, encoded, { httpOnly: true, secure: false, sameSite: 'lax', path: '/', maxAge: 60 * 10, // 10 minutes (OAuth flow timeout) }) } async del(key: string) { const cookieName = `oauth_state_${key}` this.cookies.delete(cookieName, { path: '/' }) } } export class CookieSessionStore implements NodeSavedSessionStore { constructor(private cookies: AstroCookies) {} async get(key: string): Promise { const cookieName = `oauth_session_${key}` const cookie = this.cookies.get(cookieName) if (!cookie?.value) return undefined try { const decoded = atob(cookie.value) return JSON.parse(decoded) as NodeSavedSession } catch (err) { console.warn('Failed to decode OAuth session:', err) return undefined } } async set(key: string, val: NodeSavedSession) { const cookieName = `oauth_session_${key}` const encoded = btoa(JSON.stringify(val)) this.cookies.set(cookieName, encoded, { httpOnly: true, secure: false, sameSite: 'lax', path: '/', maxAge: 60 * 60 * 24 * 30, // 30 days }) } async del(key: string) { const cookieName = `oauth_session_${key}` this.cookies.delete(cookieName, { path: '/' }) } }