{"id":16846,"library":"libts-csrfx-auth","title":"TypeScript CSRF/Session Auth Handler","description":"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.","status":"active","version":"1.0.3","language":"javascript","source_language":"en","source_url":"https://github.com/neuxdotdev/libts-csrfx-auth","tags":["javascript","libts","auth","csrf","session","cookies","typescript","web-automation","login"],"install":[{"cmd":"npm install libts-csrfx-auth","lang":"bash","label":"npm"},{"cmd":"yarn add libts-csrfx-auth","lang":"bash","label":"yarn"},{"cmd":"pnpm add libts-csrfx-auth","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library primarily uses ESM. While CommonJS might transpile, direct `require` can lead to issues with type recognition or bundling, especially in modern TypeScript projects.","wrong":"const { AuthHandler } = require('libts-csrfx-auth');","symbol":"AuthHandler","correct":"import { AuthHandler } from 'libts-csrfx-auth';"},{"note":"Use `import type` for importing interfaces or types to ensure they are stripped during compilation, preventing runtime errors or unnecessary bundle size.","wrong":"import { AuthHandlerConfig } from 'libts-csrfx-auth';","symbol":"AuthHandlerConfig","correct":"import type { AuthHandlerConfig } from 'libts-csrfx-auth';"},{"note":"Named exports are standard; avoid deep imports from internal `dist` paths which are subject to change between versions.","wrong":"import AuthError from 'libts-csrfx-auth/dist/AuthError';","symbol":"AuthError","correct":"import { AuthError } from 'libts-csrfx-auth';"}],"quickstart":{"code":"import { AuthHandler } from 'libts-csrfx-auth';\n\ninterface MyApiCredentials {\n  username: string;\n  password: string;\n}\n\n// Simulate a backend API\nconst API_BASE_URL = 'http://localhost:3000';\n\nconst authHandler = new AuthHandler({\n  apiBaseUrl: API_BASE_URL,\n  loginEndpoint: '/auth/login',\n  logoutEndpoint: '/auth/logout',\n  csrfTokenEndpoint: '/auth/csrf-token',\n  // In a real app, use a secure, persistent storage mechanism (e.g., localStorage, secure cookies)\n  // For this example, we'll use a simple in-memory store.\n  storage: {\n    get: (key) => {\n      console.log(`[Storage] Getting ${key}`);\n      return localStorage.getItem(key);\n    },\n    set: (key, value) => {\n      console.log(`[Storage] Setting ${key}=${value}`);\n      localStorage.setItem(key, value);\n    },\n    remove: (key) => {\n      console.log(`[Storage] Removing ${key}`);\n      localStorage.removeItem(key);\n    }\n  },\n  // Custom fetch function to intercept and add tokens/cookies\n  fetch: async (input, init) => {\n    const response = await fetch(input, {\n      ...init,\n      headers: {\n        'Content-Type': 'application/json',\n        // Assuming AuthHandler automatically manages Cookie and X-CSRF-Token\n        ...(init?.headers || {})\n      }\n    });\n    if (!response.ok) {\n      console.error(`API Error: ${response.status} ${response.statusText}`);\n    }\n    return response;\n  }\n});\n\nasync function runAuthFlow() {\n  const credentials: MyApiCredentials = {\n    username: process.env.TEST_USERNAME ?? 'testuser',\n    password: process.env.TEST_PASSWORD ?? 'testpass'\n  };\n\n  try {\n    console.log('--- Attempting Login ---');\n    await authHandler.login(credentials);\n    console.log('Login successful! Session should be active.');\n\n    console.log('\\n--- Fetching CSRF Token ---');\n    const csrfToken = await authHandler.getCSRFToken();\n    console.log(`Received CSRF Token: ${csrfToken ? csrfToken.substring(0, 10) + '...' : 'none'}`);\n\n    console.log('\\n--- Making a Protected Request (e.g., update profile) ---');\n    // In a real scenario, `fetch` would be wrapped by AuthHandler to inject CSRF token\n    const protectedResponse = await authHandler.fetch(`${API_BASE_URL}/profile`, {\n      method: 'POST',\n      body: JSON.stringify({ name: 'Jane Doe' })\n    });\n    if (protectedResponse.ok) {\n      console.log('Protected request successful!');\n    } else {\n      console.error('Protected request failed.');\n    }\n\n    console.log('\\n--- Attempting Logout ---');\n    await authHandler.logout();\n    console.log('Logout successful! Session should be terminated.');\n  } catch (error) {\n    console.error('Authentication flow failed:', error);\n  }\n}\n\n// Note: For a real example, you'd need a mock server at http://localhost:3000\n// that handles /auth/login, /auth/logout, /auth/csrf-token, and /profile.\n// The server should set 'Set-Cookie' headers for session and CSRF tokens\n// and validate 'X-CSRF-Token' for POST requests.\nrunAuthFlow();","lang":"typescript","description":"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`."},"warnings":[{"fix":"Review the full changelog (if available on GitHub) for `v1.0.0` or higher to identify specific API changes. Adapt your code to the new API surface, especially around `AuthHandler` configuration and method signatures.","message":"Major version 1.0.0 likely introduced breaking changes compared to 0.x. While specific details were not provided in the excerpt, major version bumps commonly indicate significant API overhauls or changes in expected behavior.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Ensure your backend properly generates a unique CSRF token for each session, sets it in a `HttpOnly, SameSite=Lax/Strict` cookie, and validates the `X-CSRF-Token` header for state-changing requests (POST, PUT, DELETE).","message":"Improper handling of CSRF tokens on the server-side can still lead to vulnerabilities, even when using this client-side library. The library facilitates token management, but the server must correctly issue, validate, and rotate tokens.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Prefer `HttpOnly` and `SameSite` cookies for session identifiers and CSRF tokens managed directly by the browser. If client-side storage is necessary, use a robust, secure abstraction and ensure tokens are short-lived.","message":"Relying solely on client-side storage (e.g., `localStorage`) for authentication tokens is less secure than `HttpOnly` cookies. If the `storage` configuration in `AuthHandler` uses insecure methods, it increases vulnerability to XSS attacks.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Verify that `apiBaseUrl` matches the origin of your backend API. If different, ensure your backend has correct CORS headers configured to allow requests from your frontend's origin.","message":"The `apiBaseUrl` configuration must accurately reflect your backend's base URL. Mismatches can lead to `CORS` issues, failed requests, or incorrect cookie domain handling, preventing session persistence.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure you are using `new AuthHandler(...)` and that your import statement is `import { AuthHandler } from 'libts-csrfx-auth';` for ESM environments, or ensure correct CommonJS syntax if the library supports it. Verify your build system handles TypeScript modules correctly.","cause":"Attempting to instantiate `AuthHandler` without `new` keyword, or incorrect import (e.g., CommonJS `require` when only ESM default export is available, or vice-versa).","error":"TypeError: AuthHandler is not a constructor"},{"fix":"Clear browser cookies and session storage, then re-authenticate. Verify the `csrfTokenEndpoint` is correctly configured and the server is consistently setting and validating CSRF tokens. Ensure no caching issues are serving stale tokens.","cause":"The CSRF token sent with a request does not match the token expected by the server. This can be due to an expired token, an invalid token (e.g., after logout/re-login), or a server-side misconfiguration.","error":"Error: CSRF token mismatch"},{"fix":"Check `apiBaseUrl` for typos. Verify your backend server is running and accessible from the client's origin. Inspect browser developer tools (Network tab) for specific HTTP errors (e.g., 404, 500, CORS related errors). Ensure `fetch` API is available in your environment (Node.js >=18, Bun, browser).","cause":"Generic network error indicating the client could not reach the API endpoint. This could be due to incorrect `apiBaseUrl`, server being down, CORS issues, or browser network restrictions.","error":"Failed to fetch"},{"fix":"The `AuthHandlerConfig` is for setting up the handler itself (endpoints, storage, fetch function). User credentials like `username` and `password` should be passed to the `login` method as arguments, for example: `authHandler.login({ username: 'user', password: 'pass' });`","cause":"Attempting to pass authentication credentials directly into `AuthHandlerConfig` instead of the `login` method.","error":"Property 'username' does not exist on type 'AuthHandlerConfig'."}],"ecosystem":"npm","meta_description":null}