{"id":16890,"library":"remix-auth-twitter","title":"Remix Auth Twitter Strategy","description":"remix-auth-twitter is an authentication plugin for Remix applications, specifically designed to integrate with the `remix-auth` library. It provides strategies for authenticating users via Twitter's (now X's) OAuth protocols, supporting both the older OAuth 1.0a (via `Twitter1Strategy`) and the newer OAuth 2.0 (via `Twitter2Strategy`). The current stable version is 4.0.0, which aligns with and requires `remix-auth@4`. Releases are primarily driven by compatibility updates with `remix-auth` major versions and changes to the Twitter API (e.g., domain changes from `twitter.com` to `x.com`). A key differentiator is its dual support for both OAuth versions and direct integration into the Remix ecosystem, abstracting much of the OAuth flow complexity.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/na2hiro/remix-auth-twitter","tags":["javascript","remix","remix-auth","auth","authentication","strategy","twitter","oauth"],"install":[{"cmd":"npm install remix-auth-twitter","lang":"bash","label":"npm"},{"cmd":"yarn add remix-auth-twitter","lang":"bash","label":"yarn"},{"cmd":"pnpm add remix-auth-twitter","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core authentication library that this package extends.","package":"remix-auth","optional":false}],"imports":[{"note":"This is the recommended strategy for Twitter OAuth 2.0. CommonJS `require` syntax is not directly supported in modern Remix projects which are typically ESM.","wrong":"const Twitter2Strategy = require('remix-auth-twitter').Twitter2Strategy;","symbol":"Twitter2Strategy","correct":"import { Twitter2Strategy } from 'remix-auth-twitter';"},{"note":"This strategy supports Twitter OAuth 1.0a. ESM imports are standard for this library.","wrong":"const Twitter1Strategy = require('remix-auth-twitter').Twitter1Strategy;","symbol":"Twitter1Strategy","correct":"import { Twitter1Strategy } from 'remix-auth-twitter';"},{"note":"The `Authenticator` class is from the `remix-auth` package, not `remix-auth-twitter`. A common mistake is trying to import it from the strategy package.","wrong":"import { Authenticator } from 'remix-auth-twitter';","symbol":"Authenticator","correct":"import { Authenticator } from 'remix-auth';"}],"quickstart":{"code":"import { Authenticator } from \"remix-auth\";\nimport { Twitter2Strategy } from \"remix-auth-twitter\";\nimport TwitterApi from \"twitter-api-v2\"; // Example external library for Twitter API calls\n\ninterface User { /* Define your user type */ id: string; username: string; accessToken: string; }\n\nexport let authenticator = new Authenticator<User>();\n\nconst clientID = process.env.TWITTER_CLIENT_ID ?? '';\nconst clientSecret = process.env.TWITTER_CLIENT_SECRET ?? '';\n\nif (!clientID || !clientSecret) {\n  throw new Error(\n    \"TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET must be provided\"\n  );\n}\n\nauthenticator.use(\n  new Twitter2Strategy(\n    {\n      clientID,\n      clientSecret,\n      callbackURL: \"https://my-app/login/callback\",\n      scopes: [\"users.read\", \"tweet.read\", \"tweet.write\"],\n    },\n    async ({ request, tokens }) => {\n      const accessToken = tokens.accessToken();\n\n      // In this example, we use an external library to get user profile details\n      const userClient = new TwitterApi(accessToken);\n      const result = await userClient.v2.me({\n        \"user.fields\": [\"profile_image_url\"],\n      });\n      // Consider robust error handling for API calls\n      const { id, username } = result.data;\n\n      // This is a placeholder for your actual user registration/lookup logic\n      async function registerUser(token: string, userId: string, uname: string): Promise<User> {\n        // In a real app, you would save/retrieve user data from a database\n        console.log(`User authenticated: ${uname} (ID: ${userId})`);\n        return { id: userId, username: uname, accessToken: token };\n      }\n      return await registerUser(accessToken, id, username);\n    }\n  )\n);\n\n// Example route action to initiate login\n/*\nexport async function action({ request }: ActionFunctionArgs) {\n  return authenticator.authenticate(\"twitter2\", request, {\n    successRedirect: \"/dashboard\",\n    failureRedirect: \"/login\",\n  });\n}\n\n// Example callback route loader\nexport async function loader({ request }: LoaderFunctionArgs) {\n  return authenticator.authenticate(\"twitter2\", request, {\n    successRedirect: \"/dashboard\",\n    failureRedirect: \"/login\",\n  });\n}\n*/","lang":"typescript","description":"This quickstart demonstrates how to configure the `Twitter2Strategy` (OAuth 2.0) with `remix-auth`, handle environment variables for credentials, and process the authentication callback to retrieve user information using an external Twitter API client."},"warnings":[{"fix":"Update `remix-auth` to version `^4.2.0` or greater: `npm install remix-auth@latest`.","message":"Version 4.0.0 introduces breaking changes to follow `remix-auth@4`. You must upgrade `remix-auth` to `^4.2.0` or higher to use `remix-auth-twitter@4.0.0`.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"No code fix is required, but be aware of potential user experience implications for existing authenticated sessions.","message":"Version 3.0.0 changed all Twitter API calls from `twitter.com` to `x.com` to reflect the domain change. Users logged in on the old domain might need to log in again.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Update your code to use `Twitter1Strategy` or `Twitter2Strategy` explicitly. If using OAuth 1.0a, ensure you're using `Twitter1Strategy` and the strategy name `twitter1` (or your custom name).","message":"Version 2.0.0 introduced OAuth 2.0 support, renaming the original `TwitterStrategy` to `Twitter1Strategy` and adding `Twitter2Strategy`. The default strategy name also changed from `twitter` to `twitter1`.","severity":"breaking","affected_versions":">=2.0.0 <3.0.0"},{"fix":"Inside your `Twitter2Strategy` `verify` callback, use an external Twitter API client (like `twitter-api-v2`) and the provided `accessToken` to query the `/2/users/me` endpoint to retrieve user profile data.","message":"When using `Twitter2Strategy` (OAuth 2.0), the user's profile information (like ID, username) is NOT automatically passed to the `verify` callback. You need to make a separate API call (e.g., to `/2/users/me`) using the obtained `accessToken` to fetch user details.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Upgrade to `remix-auth-twitter@2.0.2` or later to ensure these transitive dependencies are updated.","message":"Several security vulnerabilities were addressed in dependency `crypto-js` (CVE-2023-30062) and `word-wrap` (CVE-2023-26116).","severity":"security","affected_versions":"<2.0.2"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Set `process.env.TWITTER_CLIENT_ID` and `process.env.TWITTER_CLIENT_SECRET` (for OAuth 2.0) or `process.env.TWITTER_CONSUMER_KEY` and `process.env.TWITTER_CONSUMER_SECRET` (for OAuth 1.0a) in your Remix environment (e.g., `.env` file, deployment platform config).","cause":"Environment variables for Twitter OAuth credentials are not set or are empty.","error":"Error: TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET must be provided"},{"fix":"Check the compatibility table in the `remix-auth-twitter` README and ensure your `remix-auth` version matches the requirement for your `remix-auth-twitter` version (e.g., `remix-auth-twitter@4` requires `remix-auth@4`). Run `npm ls remix-auth remix-auth-twitter` to verify installed versions and upgrade as needed.","cause":"This error often indicates a version mismatch between `remix-auth-twitter` and its peer dependency `remix-auth`.","error":"Error: `TypeError: Class extends value #<Object> is not a constructor or null`"}],"ecosystem":"npm","meta_description":null}