A CLI for publishing standard.site documents to ATProto
sequoia.pub
standard
site
lexicon
cli
publishing
1import type { Context } from "hono";
2import { deleteCookie, getCookie, setCookie } from "hono/cookie";
3
4const SESSION_COOKIE_NAME = "session_id";
5const RETURN_TO_COOKIE_NAME = "login_return_to";
6const SESSION_TTL = 60 * 60 * 24 * 14; // 14 days in seconds
7const RETURN_TO_TTL = 600; // 10 minutes in seconds
8
9function baseCookieOptions(clientUrl: string) {
10 const isLocalhost = clientUrl.includes("localhost");
11 const hostname = new URL(clientUrl).hostname;
12 return {
13 httpOnly: true as const,
14 sameSite: "Lax" as const,
15 path: "/",
16 ...(isLocalhost ? {} : { domain: `.${hostname}`, secure: true }),
17 };
18}
19
20/**
21 * Get DID from session cookie
22 */
23export function getSessionDid(c: Context): string | null {
24 const value = getCookie(c, SESSION_COOKIE_NAME);
25 return value ? decodeURIComponent(value) : null;
26}
27
28/**
29 * Set session cookie with the user's DID
30 */
31export function setSessionCookie(
32 c: Context,
33 did: string,
34 clientUrl: string,
35): void {
36 setCookie(c, SESSION_COOKIE_NAME, encodeURIComponent(did), {
37 ...baseCookieOptions(clientUrl),
38 maxAge: SESSION_TTL,
39 });
40}
41
42/**
43 * Clear session cookie
44 */
45export function clearSessionCookie(c: Context, clientUrl: string): void {
46 deleteCookie(c, SESSION_COOKIE_NAME, baseCookieOptions(clientUrl));
47}
48
49/**
50 * Get the post-OAuth return-to URL from the short-lived cookie
51 */
52export function getReturnToCookie(c: Context): string | null {
53 const value = getCookie(c, RETURN_TO_COOKIE_NAME);
54 return value ? decodeURIComponent(value) : null;
55}
56
57/**
58 * Set a short-lived cookie that redirects back after OAuth completes
59 */
60export function setReturnToCookie(
61 c: Context,
62 returnTo: string,
63 clientUrl: string,
64): void {
65 setCookie(c, RETURN_TO_COOKIE_NAME, encodeURIComponent(returnTo), {
66 ...baseCookieOptions(clientUrl),
67 maxAge: RETURN_TO_TTL,
68 });
69}
70
71/**
72 * Clear the return-to cookie
73 */
74export function clearReturnToCookie(c: Context, clientUrl: string): void {
75 deleteCookie(c, RETURN_TO_COOKIE_NAME, baseCookieOptions(clientUrl));
76}