Session management system supporting custom storage backends and Durable Object-based sessions with cookie handling and signature validation.
Defines a session store with custom storage backend.
/**
* Creates a session store with custom storage
* @param options - Session store configuration
* @returns Session store with load, save, and remove methods
*/
function defineSessionStore<Session, SessionInputData>(options: {
/** Cookie name for session ID (default: "session_id") */
cookieName?: string;
/** Secret key for signing session IDs */
secretKey?: string;
/** Custom cookie creation function */
createCookie?: typeof createSessionCookie;
/** Get session data by ID */
get: (sessionId: string) => Promise<Session>;
/** Save session data */
set: (sessionId: string, data: SessionInputData) => Promise<void>;
/** Delete session data */
unset: (sessionId: string) => Promise<void>;
}): SessionStore<Session, SessionInputData>;
interface SessionStore<Session, SessionInputData> {
/**
* Load session from request
* @param request - HTTP request with session cookie
* @returns Session data or null if not found
*/
load(request: Request): Promise<Session | null>;
/**
* Save session data and return Set-Cookie header
* @param data - Session data to save
* @returns Set-Cookie header value
*/
save(data: SessionInputData): Promise<string>;
/**
* Remove session and return Set-Cookie header for deletion
* @param request - HTTP request with session cookie
* @returns Set-Cookie header value for deletion
*/
remove(request: Request): Promise<string>;
}Usage Example:
import { defineSessionStore } from 'rwsdk/auth';
interface UserSession {
userId: string;
email: string;
createdAt: number;
}
// In-memory storage (for demonstration)
const sessions = new Map<string, UserSession>();
const sessionStore = defineSessionStore<UserSession, UserSession>({
cookieName: 'my_session',
secretKey: process.env.SESSION_SECRET,
get: async (sessionId) => {
return sessions.get(sessionId) || null;
},
set: async (sessionId, data) => {
sessions.set(sessionId, data);
},
unset: async (sessionId) => {
sessions.delete(sessionId);
},
});
// In a route handler
async function loginHandler() {
const session = { userId: '123', email: 'user@example.com', createdAt: Date.now() };
const setCookie = await sessionStore.save(session);
return new Response('Logged in', {
headers: { 'Set-Cookie': setCookie },
});
}
async function protectedHandler(request: Request) {
const session = await sessionStore.load(request);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
return Response.json({ user: session });
}Defines a session store backed by Cloudflare Durable Objects.
/**
* Creates a session store backed by Durable Objects
* @param options - Durable Object session configuration
* @returns Session store with load, save, and remove methods
*/
function defineDurableSession<SessionDurableObject>(options: {
/** Cookie name for session ID (default: "session_id") */
cookieName?: string;
/** Secret key for signing session IDs */
secretKey?: string;
/** Custom cookie creation function */
createCookie?: typeof createSessionCookie;
/** Durable Object namespace for session storage */
sessionDurableObject: DurableObjectNamespace<SessionDurableObject>;
}): SessionStore<any, any>;
interface DurableObjectMethods<Session, SessionInputData> {
get(): Promise<Session | null>;
set(data: SessionInputData): Promise<void>;
unset(): Promise<void>;
}Usage Example:
import { defineDurableSession } from 'rwsdk/auth';
// Define in worker
async function handler(request: Request, env: any) {
const sessionStore = defineDurableSession({
cookieName: 'app_session',
secretKey: env.SESSION_SECRET,
sessionDurableObject: env.SESSION_DO,
});
const session = await sessionStore.load(request);
if (session) {
return Response.json({ authenticated: true, user: session });
}
return new Response('Not authenticated', { status: 401 });
}Creates a session cookie string with proper attributes.
/**
* Creates a session cookie string
* @param options - Cookie options
* @returns Cookie header value
*/
function createSessionCookie(options: {
/** Cookie name */
name: string;
/** Session ID value */
sessionId: string;
/** Max age in seconds (default: MAX_SESSION_DURATION) */
maxAge?: number;
}): string;Usage Example:
import { createSessionCookie } from 'rwsdk/auth';
const cookie = createSessionCookie({
name: 'session_id',
sessionId: 'abc123',
maxAge: 60 * 60 * 24 * 7, // 7 days
});
// Result: "session_id=abc123; Max-Age=604800; HttpOnly; Secure; SameSite=Lax; Path=/"Functions for generating, signing, and validating session IDs.
/**
* Generates a new signed session ID
* @param options - Generation options
* @returns Signed session ID
*/
function generateSessionId(options: {
/** Secret key for signing */
secretKey: string;
}): Promise<string>;
/**
* Signs an unsigned session ID
* @param options - Signing options
* @returns Signed session ID
*/
function signSessionId(options: {
/** Unsigned session ID */
unsignedSessionId: string;
/** Secret key for signing */
secretKey: string;
}): Promise<string>;
/**
* Validates a session ID signature
* @param options - Validation options
* @returns True if signature is valid
*/
function isValidSessionId(options: {
/** Session ID to validate */
sessionId: string;
/** Secret key used for signing */
secretKey: string;
}): Promise<boolean>;Usage Example:
import { generateSessionId, isValidSessionId } from 'rwsdk/auth';
const secretKey = process.env.SESSION_SECRET;
// Generate new session ID
const newSessionId = await generateSessionId({ secretKey });
// Validate session ID from cookie
const isValid = await isValidSessionId({
sessionId: cookieValue,
secretKey,
});
if (!isValid) {
throw new Error('Invalid session ID signature');
}/**
* Maximum session duration in milliseconds (14 days)
*/
const MAX_SESSION_DURATION: number; // 1209600000 milliseconds (14 days)import { defineApp, route, render } from 'rwsdk/worker';
import { defineSessionStore } from 'rwsdk/auth';
interface UserSession {
userId: string;
email: string;
}
// Define session store
const sessionStore = defineSessionStore<UserSession, UserSession>({
cookieName: 'auth_session',
secretKey: process.env.SESSION_SECRET,
get: async (sessionId) => {
// Get from database, KV, or Durable Object
const data = await env.KV.get(sessionId);
return data ? JSON.parse(data) : null;
},
set: async (sessionId, data) => {
await env.KV.put(sessionId, JSON.stringify(data), {
expirationTtl: 60 * 60 * 24 * 14, // 14 days
});
},
unset: async (sessionId) => {
await env.KV.delete(sessionId);
},
});
// Login route
const loginRoute = route('/login', {
POST: async (request: Request) => {
const { email, password } = await request.json();
// Validate credentials
const user = await validateUser(email, password);
if (!user) {
return new Response('Invalid credentials', { status: 401 });
}
// Create session
const setCookie = await sessionStore.save({
userId: user.id,
email: user.email,
});
return new Response('Logged in', {
status: 200,
headers: { 'Set-Cookie': setCookie },
});
},
});
// Logout route
const logoutRoute = route('/logout', {
POST: async (request: Request) => {
const setCookie = await sessionStore.remove(request);
return new Response('Logged out', {
status: 200,
headers: { 'Set-Cookie': setCookie },
});
},
});
// Protected route
const dashboardRoute = route('/dashboard', async (request: Request) => {
const session = await sessionStore.load(request);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
return <Dashboard user={session} />;
});
export default defineApp([
render(Document, [
loginRoute,
logoutRoute,
dashboardRoute,
]),
]);