Statusphere, but in atcute and SvelteKit
atproto svelte sveltekit drizzle atcute typescript
at trunk 82 lines 1.9 kB view raw
1import { error } from '@sveltejs/kit'; 2 3import { Client } from '@atcute/client'; 4import type { Did } from '@atcute/lexicons'; 5import { isDid } from '@atcute/lexicons/syntax'; 6import { 7 AuthMethodUnsatisfiableError, 8 TokenInvalidError, 9 TokenRefreshError, 10 TokenRevokedError, 11} from '@atcute/oauth-node-client'; 12 13import { getRequestEvent } from '$app/server'; 14 15import { getSignedCookie } from '$lib/server/auth/signed-cookie'; 16import { oauth } from '$lib/server/oauth'; 17 18export const SESSION_COOKIE = 'statusphere_session'; 19 20export interface Session { 21 did: Did; 22} 23 24export interface AuthContext { 25 session: Session; 26 client: Client; 27} 28 29const isSessionInvalidError = (err: unknown): boolean => { 30 return ( 31 err instanceof TokenRefreshError || 32 err instanceof TokenInvalidError || 33 err instanceof TokenRevokedError || 34 err instanceof AuthMethodUnsatisfiableError 35 ); 36}; 37 38/** 39 * requires an authenticated session, throwing if not signed in or session is invalid. 40 * caches the result in locals for successive calls within the same request. 41 * @returns authenticated session and client 42 * @throws if not signed in or OAuth session is invalid 43 */ 44export const requireAuth = async (): Promise<AuthContext> => { 45 const { locals, cookies } = getRequestEvent(); 46 47 // return cached result if available 48 if (locals.auth) { 49 return locals.auth; 50 } 51 52 const did = getSignedCookie(cookies, SESSION_COOKIE); 53 if (!did) { 54 error(401, `not signed in`); 55 } 56 57 if (!isDid(did)) { 58 cookies.delete(SESSION_COOKIE, { path: '/' }); 59 error(401, `not signed in`); 60 } 61 62 try { 63 const session = await oauth.restore(did); 64 const client = new Client({ handler: session }); 65 66 const auth: AuthContext = { 67 session: { did }, 68 client, 69 }; 70 71 locals.auth = auth; 72 return auth; 73 } catch (err) { 74 if (isSessionInvalidError(err)) { 75 cookies.delete(SESSION_COOKIE, { path: '/' }); 76 77 error(401, `session expired`); 78 } 79 80 throw err; 81 } 82};