{"library":"remix-auth-totp","title":"Remix Auth TOTP","description":"remix-auth-totp is an authentication strategy for Remix Auth that enables Time-Based One-Time Password (TOTP) based authentication, including support for email-code and magic link workflows. The current stable version is 4.0.0, which introduced compatibility with Remix Auth v4 and React Router v7. The package maintains a regular release cadence, with major versions often aligning with upstream Remix Auth updates, and minor/patch releases addressing features and bug fixes. Key differentiators include built-in magic link functionality, support for Cloudflare Pages, enhanced security through JWE encryption and SHA256 hashing (since v3.2.0), and a strong TypeScript foundation. A significant architectural shift in v3.0.0 eliminated direct database reliance, simplifying its integration model.","language":"javascript","status":"active","last_verified":"Wed Apr 22","install":{"commands":["npm install remix-auth-totp"],"cli":null},"imports":["import { TOTPStrategy } from 'remix-auth-totp';","import type { TOTPStrategyOptions } from 'remix-auth-totp';","import { TOTPError } from 'remix-auth-totp';"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import { Authenticator } from \"remix-auth\";\nimport { TOTPStrategy } from \"remix-auth-totp\";\nimport { createCookieSessionStorage, redirect } from \"@remix-run/node\";\n\ninterface User {\n  id: string;\n  email: string;\n}\n\n// 1. Setup session storage\nconst sessionStorage = createCookieSessionStorage({\n  cookie: {\n    name: \"__session\",\n    httpOnly: true,\n    sameSite: \"lax\",\n    path: \"/\",\n    secrets: [process.env.SESSION_SECRET ?? 'a_secret_key'], // Replace with actual secret\n    secure: process.env.NODE_ENV === \"production\",\n  },\n});\n\n// 2. Initialize Authenticator\nexport const authenticator = new Authenticator<User>(sessionStorage);\n\n// Mock database for TOTP secrets (replace with your actual database)\nconst userTotpSecrets = new Map<string, string>();\nuserTotpSecrets.set(\"test@example.com\", process.env.TOTP_USER_SECRET ?? 'A_VERY_SECURE_SECRET');\n\n// 3. Register the TOTP Strategy\nauthenticator.use(\n  new TOTPStrategy(\n    {\n      secret: async ({ email }) => {\n        // Fetch the user's TOTP secret from your database\n        const secret = userTotpSecrets.get(email);\n        if (!secret) {\n          throw new Error(`TOTP not configured for ${email}.`);\n        }\n        return secret;\n      },\n      sendTOTP: async ({ email, code, magicLink, request }) => {\n        // In a real app, send `code` or `magicLink` via email/SMS to `email`.\n        console.log(`Sending code ${code} or magic link to ${email}`);\n        // Example: await sendEmail({ to: email, subject: \"Your TOTP Code\", body: `Code: ${code}. Or login: ${magicLink}` });\n      },\n      // You can add other options like `maxAge`, `issuer`, `magicLinkPath`\n    },\n    async ({ email, code, magicLink }) => {\n      // Verify the user and return the user object upon successful authentication.\n      // This is where you would fetch the user from your DB and return it.\n      if (email === \"test@example.com\" && (code === \"123456\" || magicLink)) { // Simplified logic\n        return { id: \"user-abc\", email: \"test@example.com\" };\n      }\n      throw new Error(\"Invalid TOTP or Magic Link.\");\n    }\n  ),\n  \"totp\" // Unique name for this strategy\n);\n\n// 4. Example Remix Action (e.g., in `app/routes/login.tsx`)\nexport async function action({ request }: { request: Request }) {\n  try {\n    return await authenticator.authenticate(\"totp\", request, {\n      successRedirect: \"/dashboard\",\n      failureRedirect: \"/login?error=true\",\n    });\n  } catch (error) {\n    if (error instanceof Response && error.status >= 300 && error.status < 400) {\n      throw error; // Propagate redirects from authenticator (e.g., magic link sent)\n    }\n    console.error(\"Login failed:\", error);\n    return redirect(\"/login?error=true\");\n  }\n}","lang":"typescript","description":"Demonstrates setting up `remix-auth-totp` with `remix-auth` to initialize the strategy with `secret` and `sendTOTP` callbacks, and handle an authentication attempt in a Remix action.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}