TypeScript CSRF/Session Auth Handler

1.0.3 · active · verified Wed Apr 22

libts-csrfx-auth is a TypeScript-first library designed for managing web session authentication, including CSRF token handling and cookie persistence. Currently at stable version 1.0.3, it has a recent and active release cadence, evidenced by several minor releases following its 1.0.0 major launch. Inspired by Rust's `cekunit-client`, this library focuses on providing a minimal yet robust solution for client-side or web automation authentication flows. Its core utility lies in abstracting the complexities of session management, secure CSRF token exchange, and automatically maintaining authentication state via HTTP cookies, making it suitable for applications requiring resilient and secure web session handling in Node.js or Bun environments.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates the core authentication flow: logging in, fetching a CSRF token, making a protected request, and logging out, showing how to initialize and use the `AuthHandler`.

import { AuthHandler } from 'libts-csrfx-auth';

interface MyApiCredentials {
  username: string;
  password: string;
}

// Simulate a backend API
const API_BASE_URL = 'http://localhost:3000';

const authHandler = new AuthHandler({
  apiBaseUrl: API_BASE_URL,
  loginEndpoint: '/auth/login',
  logoutEndpoint: '/auth/logout',
  csrfTokenEndpoint: '/auth/csrf-token',
  // In a real app, use a secure, persistent storage mechanism (e.g., localStorage, secure cookies)
  // For this example, we'll use a simple in-memory store.
  storage: {
    get: (key) => {
      console.log(`[Storage] Getting ${key}`);
      return localStorage.getItem(key);
    },
    set: (key, value) => {
      console.log(`[Storage] Setting ${key}=${value}`);
      localStorage.setItem(key, value);
    },
    remove: (key) => {
      console.log(`[Storage] Removing ${key}`);
      localStorage.removeItem(key);
    }
  },
  // Custom fetch function to intercept and add tokens/cookies
  fetch: async (input, init) => {
    const response = await fetch(input, {
      ...init,
      headers: {
        'Content-Type': 'application/json',
        // Assuming AuthHandler automatically manages Cookie and X-CSRF-Token
        ...(init?.headers || {})
      }
    });
    if (!response.ok) {
      console.error(`API Error: ${response.status} ${response.statusText}`);
    }
    return response;
  }
});

async function runAuthFlow() {
  const credentials: MyApiCredentials = {
    username: process.env.TEST_USERNAME ?? 'testuser',
    password: process.env.TEST_PASSWORD ?? 'testpass'
  };

  try {
    console.log('--- Attempting Login ---');
    await authHandler.login(credentials);
    console.log('Login successful! Session should be active.');

    console.log('\n--- Fetching CSRF Token ---');
    const csrfToken = await authHandler.getCSRFToken();
    console.log(`Received CSRF Token: ${csrfToken ? csrfToken.substring(0, 10) + '...' : 'none'}`);

    console.log('\n--- Making a Protected Request (e.g., update profile) ---');
    // In a real scenario, `fetch` would be wrapped by AuthHandler to inject CSRF token
    const protectedResponse = await authHandler.fetch(`${API_BASE_URL}/profile`, {
      method: 'POST',
      body: JSON.stringify({ name: 'Jane Doe' })
    });
    if (protectedResponse.ok) {
      console.log('Protected request successful!');
    } else {
      console.error('Protected request failed.');
    }

    console.log('\n--- Attempting Logout ---');
    await authHandler.logout();
    console.log('Logout successful! Session should be terminated.');
  } catch (error) {
    console.error('Authentication flow failed:', error);
  }
}

// Note: For a real example, you'd need a mock server at http://localhost:3000
// that handles /auth/login, /auth/logout, /auth/csrf-token, and /profile.
// The server should set 'Set-Cookie' headers for session and CSRF tokens
// and validate 'X-CSRF-Token' for POST requests.
runAuthFlow();

view raw JSON →