Twitter Authentication with React and Node.js

Abhilash TU
4 min readJun 10, 2024

--

This guide will walk you through setting up Twitter authentication in a React application using a Node.js backend. The application will allow users to log in with their Twitter account, fetch their followers, and display them in the React app.

Prerequisites

  • Node.js and npm are installed on your machine.
  • Twitter Developer Account and a Twitter App set up.
  • Basic knowledge of JavaScript, React, and Express.js.
  • You need Basic tier Access to fetch Followers of related data, by default we only get Free tier Access.

Step 1: Setting Up the Twitter Developer Account

  1. Go to the Twitter Developer Portal.
  2. Create a new project and a new app within that project.
  3. Select Project → Settings → User authentication settings.
  4. Set the Type of App to Web App, Automated App Or Bot
  5. Setup Callback URL / REDIRECT URL to http://localhost:5000/callback.
  6. Set Website URL.
  7. Set up the OAuth 2.0 authentication settings with the callback URL: http://localhost:5000/callback
  8. In your app Keys and tokens, find and copy the following credentials:
  • In OAuth 2.0 Client ID and Client Secret
  • Client ID and Client Secret

Step 2: Setting Up the Backend Server

  1. Create a new directory for your project and initialize a new Node.js project:
mkdir twitter-auth-app cd twitter-auth-app npm init -y
  • Install the necessary packages:
npm install express cors dotenv axios twitter-api-s
  1. Create a .env file in the root directory and add your Twitter API credentials:
CLIENT_ID=your-twitter-api-key CLIENT_SECRET=your-twitter-api-secret-key
  • Create a server.js file and add the following code:
// This is the Express server that will handle OAuth flow
// and will receive the access token from Twitter
// and will also be responsible for fetching the user's followers
// and will be used by the client to make requests to Twitter API
//
// The server is created to separate the logic of handling the OAuth flow
// and the logic of fetching the user's followers and to avoid
// potential security issues that can arise from mixing the two
//
// The server is also responsible for setting up CORS to allow
// the frontend to make requests to the server

const { Client, auth } = require("twitter-api-sdk");
const express = require("express");
const axios = require("axios");
// const dotenv = require("dotenv");
const cors = require("cors");
let accessToken = "";
// dotenv.config();

const app = express();
app.use(cors());

const authClient = new auth.OAuth2User({
client_id: "ZURHVmZhM0FxYm0yWDZBNTZ6c2g6MTpjaQ",
client_secret: "489DpfNasqqX5m3UnLSGyrE5968gCBB8EufXavIMKWGvxXujhY",
callback: "http://localhost:5000/callback",
scopes: ["tweet.read", "users.read"],
});

const client = new Client(authClient);

const STATE = "my-state";

app.get("/callback", async function (req, res) {
try {
const { code, state } = req.query;
if (state !== STATE) return res.status(500).send("State isn't matching");
accessToken = (await authClient.requestAccessToken(code)).token
.access_token;
console.log("AccessToken: " + JSON.stringify(accessToken));

res.send(`
<html>
<body>
<p>You have been authenticated with this platform. You can close the window now.</p>
<script>
// Pass the access token and status to the parent window
window.opener.postMessage({ token: ${JSON.stringify(
accessToken
)}, status: "Login successful" }, "*");

// Close the window after a delay
setTimeout(() => {
window.close();
}, 3000); // 3 seconds delay
</script>
</body>
</html>
`);
} catch (error) {
console.log(error);
}
});

app.get("/login", async function (req, res) {
const authUrl = authClient.generateAuthURL({
state: STATE,
code_challenge_method: "s256",
});
console.log(authUrl);
res.redirect(authUrl);
});

app.get("/tweets", async function (req, res) {
const tweets = await client.tweets.findTweetById("20");
res.send(tweets.data);
});

app.get("/revoke", async function (req, res) {
try {
const response = await authClient.revokeAccessToken();
res.send(response);
} catch (error) {
console.log(error);
}
});

app.post("/followers", async (req, res) => {
try {
// const { accessToken } = req.body;

const userResponse = await axios.get("https://api.twitter.com/2/users/me", {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
});
const userId = userResponse.data.data.id;
console.log("User ID: " + userId);

const response = await axios.get(
`https://api.twitter.com/2/users/${userId}/followers`,
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
}
);

res.send(response.data.data);
} catch (error) {
console.error("Error fetching followers:", error);
res.status(500).send("Failed to fetch followers");
}
});

app.use(
cors({
origin: "https://localhost:3000",
})
);

app.listen(5000, () => {
console.log(`Go here to login: http://localhost:5000/login`);
});

Step 3: Setting Up the React Client

  1. Create a new React application in the twitter-auth-app directory:
npx create-react-app client cd client
  1. Install axios for making HTTP requests:
npm install axiosUpdate src/App.js with the following code:

Create a `server.js` file and add the following code:

'use client'
import axios from "axios";
import CustomCard from "../Components/Card";
import styles from "../page.module.css";
import { useEffect, useState } from "react";
export default function page() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userID, setUserID] = useState('');
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [picture, setPicture] = useState('');

const [accessToken, setAccessToken] = useState(null);
const [loginStatus, setLoginStatus] = useState(null);
const [followers, setFollowers] = useState([]);

useEffect(() => {
const handleMessage = (event) => {
if (event.origin !== "http://localhost:5000") return;

const { token, status } = event.data;

if (token) {
setAccessToken(token);
setLoginStatus(status);
}
};

window.addEventListener("message", handleMessage);

return () => {
window.removeEventListener("message", handleMessage);
};
}, []);

const handleLogin = async () => {
try {
// const response = await axios.get('http://localhost:5000/login');
// const authUrl = response.data.url;
window.open("http://localhost:5000/login", '_blank', 'width=600,height=700');

} catch (error) {
console.error('Error initiating Twitter login', error);
}

};

const handleLogout = async () => {

};

const handleFetchEmail = async () => {

};

const handleFetchFollowers = async () => {
try {
const response = await axios.post("http://localhost:5000/followers", {
accessToken,
});
console.log(response.data)
} catch (error) {
console.error("Error fetching followers", error);
}
};

const handleFetchPosts = async () => {

};

const handleFetchPermissions = async () => {

};

return (
<main className={styles.main}>
<CustomCard >

<div className={styles.btnCont}>
<button className={styles.btn} onClick={handleLogin}>Login</button>
<button className={styles.btn} onClick={handleFetchFollowers}>Fetch Followers</button>
{/* <button className={styles.btn} onClick={handleLogout}>Logout</button>
<button className={styles.btn} onClick={handleFetchEmail}>Fetch Email</button>

<button className={styles.btn} onClick={handleFetchPosts}>Fetch Posts</button>
<button className={styles.btn} onClick={handleFetchPermissions}>User Permission</button> */}

</div>
</CustomCard>
</main>
);
}

Step 4: Running the Application

  1. Start the Backend Server:
cd twitter-auth-app node server.js
  1. Start the React Client: Open a new terminal window and run:
cd twitter-auth-app/client npm start

Conclusion

You have successfully set up Twitter authentication in a React application using a Node.js backend. Users can log in with their Twitter account, fetch followers, and display them in the React app. This setup provides a solid foundation for further enhancements, such as additional Twitter API interactions or improved user interface elements.

--

--

Abhilash TU
0 Followers

Being curious about science and tech is more like a lifestyle, and I devote myself to it.