or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdclient-runtime.mddatabase.mde2e-testing.mdindex.mdrealtime.mdrouting.mdsynced-state.mdturnstile.mdvite-plugin.mdworker-runtime.md
tile.json

authentication.mddocs/

Authentication & Sessions

Session management system supporting custom storage backends and Durable Object-based sessions with cookie handling and signature validation.

Capabilities

Custom Session Store

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 });
}

Durable Object Session Store

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 });
}

Cookie Creation

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=/"

Session ID Operations

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');
}

Constants

/**
 * Maximum session duration in milliseconds (14 days)
 */
const MAX_SESSION_DURATION: number; // 1209600000 milliseconds (14 days)

Complete Authentication Example

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,
  ]),
]);