import { cookies } from 'next/headers'; import { verifySurrealJwt, type UserSession } from './jwt'; import { getOAuthClient } from './oauth-client'; import { Agent } from '@atproto/api'; import jwt from 'jsonwebtoken'; /** * Gets the current authenticated user from the session cookie. * This function should be called from Server Components or API routes. * * @returns The user session if authenticated, null otherwise */ export async function getCurrentUser(): Promise { const cookieStore = await cookies(); const authCookie = cookieStore.get('ponderants-auth'); if (!authCookie?.value) { return null; } return verifySurrealJwt(authCookie.value); } /** * Get the authenticated ATproto agent for the current user. * * Automatically refreshes tokens if needed. The OAuth client * handles token refresh transparently and updates the sessionStore. * * @returns Agent instance for making authenticated ATproto API calls, * or null if user is not authenticated */ export async function getAuthenticatedAgent(): Promise { try { // Get user DID from our SurrealDB JWT cookie const cookieStore = await cookies(); const authCookie = cookieStore.get('ponderants-auth'); if (!authCookie) { return null; } // Decode JWT to get DID (we don't verify here since SurrealDB will verify) const payload = jwt.decode(authCookie.value) as { sub: string } | null; if (!payload?.sub) { return null; } const did = payload.sub; console.log('[Session] Restoring session for DID:', did); // Restore session from OAuth client // This will automatically refresh tokens if they're expired const client = await getOAuthClient(); const session = await client.restore(did); console.log('[Session] ✓ Session restored'); // Create agent with session return new Agent(session); } catch (error) { console.error('[Session] Failed to restore session:', error); return null; } } /** * Sign out the current user. * * Revokes tokens with the PDS and clears the session from storage. * Also clears our app's JWT cookie. */ export async function signOut(): Promise { try { const agent = await getAuthenticatedAgent(); if (agent) { console.log('[Session] Signing out user:', agent.did); // Revoke session (calls PDS to revoke tokens) const session = (agent as any).session; if (session?.signOut) { await session.signOut(); console.log('[Session] ✓ Session revoked with PDS'); } } } catch (error) { console.error('[Session] Sign out error:', error); // Continue to clear cookie even if revocation fails } // Clear our app's cookie const cookieStore = await cookies(); cookieStore.delete('ponderants-auth'); console.log('[Session] ✓ Local session cleared'); } /** * Get the current user's DID from the session cookie. * * This is a lightweight check that doesn't require restoring * the full OAuth session. Useful for quick authorization checks. * * @returns User's DID or null if not authenticated */ export async function getCurrentUserDid(): Promise { try { const cookieStore = await cookies(); const authCookie = cookieStore.get('ponderants-auth'); if (!authCookie) { return null; } const payload = jwt.decode(authCookie.value) as { sub: string } | null; return payload?.sub || null; } catch { return null; } }