Remix Auth Twitter Strategy
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.
Common errors
-
Error: TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET must be provided
cause Environment variables for Twitter OAuth credentials are not set or are empty.fixSet `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). -
Error: `TypeError: Class extends value #<Object> is not a constructor or null`
cause This error often indicates a version mismatch between `remix-auth-twitter` and its peer dependency `remix-auth`.fixCheck 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.
Warnings
- breaking 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`.
- breaking 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.
- breaking 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`.
- gotcha 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.
- security Several security vulnerabilities were addressed in dependency `crypto-js` (CVE-2023-30062) and `word-wrap` (CVE-2023-26116).
Install
-
npm install remix-auth-twitter -
yarn add remix-auth-twitter -
pnpm add remix-auth-twitter
Imports
- Twitter2Strategy
const Twitter2Strategy = require('remix-auth-twitter').Twitter2Strategy;import { Twitter2Strategy } from 'remix-auth-twitter'; - Twitter1Strategy
const Twitter1Strategy = require('remix-auth-twitter').Twitter1Strategy;import { Twitter1Strategy } from 'remix-auth-twitter'; - Authenticator
import { Authenticator } from 'remix-auth-twitter';import { Authenticator } from 'remix-auth';
Quickstart
import { Authenticator } from "remix-auth";
import { Twitter2Strategy } from "remix-auth-twitter";
import TwitterApi from "twitter-api-v2"; // Example external library for Twitter API calls
interface User { /* Define your user type */ id: string; username: string; accessToken: string; }
export let authenticator = new Authenticator<User>();
const clientID = process.env.TWITTER_CLIENT_ID ?? '';
const clientSecret = process.env.TWITTER_CLIENT_SECRET ?? '';
if (!clientID || !clientSecret) {
throw new Error(
"TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET must be provided"
);
}
authenticator.use(
new Twitter2Strategy(
{
clientID,
clientSecret,
callbackURL: "https://my-app/login/callback",
scopes: ["users.read", "tweet.read", "tweet.write"],
},
async ({ request, tokens }) => {
const accessToken = tokens.accessToken();
// In this example, we use an external library to get user profile details
const userClient = new TwitterApi(accessToken);
const result = await userClient.v2.me({
"user.fields": ["profile_image_url"],
});
// Consider robust error handling for API calls
const { id, username } = result.data;
// This is a placeholder for your actual user registration/lookup logic
async function registerUser(token: string, userId: string, uname: string): Promise<User> {
// In a real app, you would save/retrieve user data from a database
console.log(`User authenticated: ${uname} (ID: ${userId})`);
return { id: userId, username: uname, accessToken: token };
}
return await registerUser(accessToken, id, username);
}
)
);
// Example route action to initiate login
/*
export async function action({ request }: ActionFunctionArgs) {
return authenticator.authenticate("twitter2", request, {
successRedirect: "/dashboard",
failureRedirect: "/login",
});
}
// Example callback route loader
export async function loader({ request }: LoaderFunctionArgs) {
return authenticator.authenticate("twitter2", request, {
successRedirect: "/dashboard",
failureRedirect: "/login",
});
}
*/