social components
inlay.at
atproto
components
sdui
1// auth/session.ts
2import "server-only";
3import { cookies } from "next/headers";
4import { getIronSession } from "iron-session";
5import { Agent } from "@atproto/api";
6import { TokenRefreshError } from "@atproto/oauth-client-node";
7import { refresh } from "next/cache";
8import { getOAuthClient, getCookieSecret } from "./client";
9
10export type SessionData = {
11 did?: string;
12};
13
14const SESSION_OPTIONS = {
15 cookieName: "inlay_session",
16 password: "", // Set dynamically
17 cookieOptions: {
18 secure: process.env.NODE_ENV === "production",
19 httpOnly: true,
20 sameSite: "lax" as const,
21 },
22};
23
24export async function getSession() {
25 const cookieStore = await cookies();
26 return getIronSession<SessionData>(cookieStore, {
27 ...SESSION_OPTIONS,
28 password: getCookieSecret(),
29 });
30}
31
32export async function getCurrentDid(): Promise<string | null> {
33 const session = await getSession();
34 return session.did || null;
35}
36
37export async function getSessionAgent() {
38 const did = await getCurrentDid();
39 if (!did) return null;
40
41 try {
42 const client = await getOAuthClient();
43 return await client.restore(did);
44 } catch (err) {
45 if (err instanceof TokenRefreshError) {
46 console.log("[session] TokenRefreshError, clearing session for", did);
47 const session = await getSession();
48 session.destroy();
49 refresh();
50 } else {
51 console.error("[session] Failed to restore OAuth session for", did, err);
52 }
53 return null;
54 }
55}
56
57/**
58 * Get a service JWT for authenticating to a component.
59 * This calls the user's PDS to get a short-lived token signed by the user's key.
60 * The component can verify this token cryptographically.
61 */
62export async function getServiceJwt(
63 componentDid: string,
64 procedure?: string
65): Promise<string | null> {
66 const session = await getSessionAgent();
67 if (!session) return null;
68
69 try {
70 const agent = new Agent(session);
71 const response = await agent.com.atproto.server.getServiceAuth({
72 aud: componentDid,
73 lxm: procedure,
74 });
75 return response.data.token;
76 } catch (err) {
77 console.error("Failed to get service JWT:", err);
78 return null;
79 }
80}