A minimal starter for ATProto logins in Astro
1import type { AstroCookies } from 'astro'
2
3export type SessionData = { did?: string }
4
5const COOKIE_NAME = 'sid'
6
7// Simple cookie-based session using Web Crypto API
8export class Session {
9 private data: SessionData = {}
10 private cookies: AstroCookies
11
12 constructor(cookies: AstroCookies, data: SessionData = {}) {
13 this.cookies = cookies
14 this.data = data
15 }
16
17 get did() {
18 return this.data.did
19 }
20
21 set did(value: string | undefined) {
22 this.data.did = value
23 }
24
25 async save() {
26 const jsonData = JSON.stringify(this.data)
27 // For simplicity, we'll just base64 encode the data
28 // In production, you'd want proper encryption
29 const encoded = btoa(jsonData)
30
31 this.cookies.set(COOKIE_NAME, encoded, {
32 httpOnly: true,
33 secure: false,
34 sameSite: 'lax',
35 path: '/',
36 maxAge: 60 * 60 * 24 * 30, // 30 days
37 })
38 }
39
40 destroy() {
41 this.data = {}
42 this.cookies.delete(COOKIE_NAME, { path: '/' })
43 }
44}
45
46export function getSession(cookies: AstroCookies): Session {
47 const cookie = cookies.get(COOKIE_NAME)
48
49 if (!cookie?.value) {
50 return new Session(cookies)
51 }
52
53 try {
54 const decoded = atob(cookie.value)
55 const data = JSON.parse(decoded) as SessionData
56 return new Session(cookies, data)
57 } catch (err) {
58 console.warn('Failed to decode session:', err)
59 return new Session(cookies)
60 }
61}