Google OAuth Authentication with React, Node.js, and Express

Hi there! I'm Aditya, a passionate Full-Stack Developer driven by a love for turning concepts into captivating digital experiences. With a blend of creativity and technical expertise, I specialize in crafting user-friendly websites and applications that leave a lasting impression. Let's connect and bring your digital vision to life!
Google Sign-In is one of the easiest ways to authenticate users without asking them to create and remember another password. In this guide, you'll learn how to integrate Google OAuth into a React application using @react-oauth/google and verify users securely on a Node.js backend.
By the end of this guide, you'll have:
- A React frontend with Google Sign-In
- A Node.js backend that verifies Google ID tokens
- JWT-based authentication
- Automatic user creation for first-time sign-ins
Prerequisites
Before getting started, make sure you have:
| Requirement | Description |
|---|---|
| Node.js | Installed on your machine |
| React | Vite or Create React App |
| Express | Backend server |
| MongoDB | Database for storing users |
| Google Cloud Account | Required to create OAuth credentials |
Create Google OAuth Credentials
Open the Google Cloud Console and navigate to the Credentials page.
Create a new OAuth Client ID with the following settings.
| Option | Value |
|---|---|
| Credential Type | OAuth Client ID |
| Application Type | Web Application |
After creating the credentials, copy the generated Client ID. You'll use it in both the frontend and backend.
Frontend Setup
Install Required Package
npm install @react-oauth/google
Configure Environment Variables
Create a .env file in your frontend project.
VITE_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
VITE_BACKEND_URL=http://localhost:5000
Wrap Your Application
Update your main.tsx file.
import { GoogleOAuthProvider } from "@react-oauth/google";
const clientId = import.meta.env.VITE_GOOGLE_CLIENT_ID;
<GoogleOAuthProvider clientId={clientId}>
<App />
</GoogleOAuthProvider>;
This provider makes the Google authentication context available throughout your application.
Create the Google Authentication Component
Create a new component called GoogleAuth.tsx.
import { GoogleLogin } from "@react-oauth/google";
import axios from "axios";
const GoogleAuth = () => {
const handleSuccess = async (credentialResponse) => {
try {
const res = await axios.post(
`${import.meta.env.VITE_BACKEND_URL}/api/v1/google-signin`,
{
credential: credentialResponse.credential,
}
);
localStorage.setItem("token", res.data.token);
alert("Login successful");
} catch (err) {
console.error("Login error:", err);
alert("Login failed");
}
};
return (
<GoogleLogin
onSuccess={handleSuccess}
onError={() => alert("Google Login Failed")}
/>
);
};
export default GoogleAuth;
Once the user signs in successfully, Google returns an ID token. This token is then sent to the backend for verification.
Common Frontend Mistakes
| Mistake | Why It Causes Problems |
|---|---|
Missing GoogleOAuthProvider |
Google Login will not initialize |
Incorrect clientId |
Authentication will fail |
| Sending requests to the frontend instead of the backend | OAuth verification must happen on the server |
| Forgetting to define environment variables | The application won't be able to access the Google Client ID or backend URL |
Backend Setup
Install Required Package
npm install google-auth-library
Configure Environment Variables
Create a .env file in the backend.
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
JWT_SECRET=your_jwt_secret_key
Create the Authentication Controller
Create a file named googleAuth.ts.
import { OAuth2Client } from "google-auth-library";
import User from "../models/user";
import jwt from "jsonwebtoken";
const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);
export const googleAuth = async (req, res) => {
try {
const { credential } = req.body;
const ticket = await client.verifyIdToken({
idToken: credential,
audience: process.env.GOOGLE_CLIENT_ID,
});
const payload = ticket.getPayload();
const {
email,
name,
sub: googleID,
} = payload;
let user = await User.findOne({ email });
if (!user) {
user = await User.create({
email,
username: name,
googleID,
});
}
const token = jwt.sign(
{
id: user._id,
},
process.env.JWT_SECRET,
{
expiresIn: "7d",
}
);
res.status(200).json({
token,
user,
});
} catch (error) {
console.error(error);
res.status(401).json({
message: "Google sign-in failed",
});
}
};
The backend verifies the ID token received from Google. If the token is valid, it either creates a new user or logs in an existing one before returning a JWT.
Register the Route
Import the controller into your main server file.
import { googleAuth } from "./controllers/googleAuth";
Register the route.
app.post("/api/v1/google-signin", googleAuth);
User Schema
A simple user schema is enough for Google authentication.
const userSchema = new mongoose.Schema({
username: String,
email: {
type: String,
required: true,
unique: true,
},
password: String,
googleID: String,
});
If your application supports both email/password authentication and Google Sign-In, keeping the password field optional is a common approach.
Authentication Flow
The complete authentication process looks like this:
User
│
▼
Google Login Button
│
▼
Google Authentication
│
▼
Receive ID Token
│
▼
Send Token to Express Backend
│
▼
Verify Token with Google
│
▼
Find or Create User
│
▼
Generate JWT
│
▼
Return JWT + User Data
│
▼
Store JWT in Frontend
Final Project Structure
frontend
├── src
│ ├── components
│ │ └── GoogleAuth.tsx
│ ├── App.tsx
│ └── main.tsx
├── .env
backend
├── controllers
│ └── googleAuth.ts
├── models
│ └── user.ts
├── index.ts
└── .env
Conclusion
Integrating Google OAuth removes the friction of traditional sign-up forms while providing a secure authentication flow. Instead of managing passwords yourself, you rely on Google's identity platform, verify the ID token on your backend, and issue your own JWT for application access.
With this setup in place, users can sign in with a single click, while your backend remains responsible for authentication, authorization, and session management.



