Implementing Google OAuth in MERN

01. Introduction

Welcome to the world of the MERN stack! This guide will cover the basics of MongoDB, Express.js, React.js, and Node.js, along with interview tips. Whether a novice or an expert, you’ll gain the knowledge to build robust web applications. Let’s dive in and explore the power of the MERN stack.

1.1 Understanding the MERN Stack

The MERN stack combines MongoDB, Express.js, React.js, and Node.js to create modern web applications. This full-stack JavaScript approach ensures a seamless development process.

MERN Stack

Picture 01: MERN stack Architecture

  • MongoDB: A flexible, scalable NoSQL database that uses a document-based model, allowing for faster development and easy schema updates.
  • Express.js: A minimalist web application framework for Node.js, offering routing, middleware, and template engines to simplify HTTP request handling and API building.
  • React.js: A popular library for building user interfaces with a component-based architecture, providing efficient rendering and user interaction management.
  • Node.js: A server-side JavaScript runtime that enables scalable, high-performance web applications with an event-driven, non-blocking I/O model.

The integration of these components allows for efficient development and code reuse. This guide will delve into each component’s features, best practices, and advanced concepts, equipping you to build powerful web applications with the MERN stack.

Let's start with the project.

02. Implementing Google OAuth

In my previous article, I explained step by step how to implement Google OAuth. You can refer to my previous article, "Understanding Google OAuth (Open Authorization)," for more details.

Here is a brief overview of the steps.

  • Google API Console.
  • Create a new project.
  • APIs and Services.
  • Create OAuth 2.0 Credentials.
  • Configure the OAuth consent screen.
  • Configure the OAuth client ID.
  • Download the credentials.

I covered this topic in my previous article. Please read that article before continuing with this one. Now, let's continue with this article.

Web Server Applications

Picture 02: Web Server Applications

The authorization process starts when your application redirects a browser to a specified Google URL. This URL contains query parameters that define the type of access being requested. Google manages user authentication, session selection, and user consent. Upon completion, an authorization code is provided, which the application can exchange for an access token and a refresh token

Go to this link: https://console.cloud.google.com/cloud-resource-manager

2.1 Get the Google API key and Credentials

Step 01

Google API key

Picture 03: Cloud resource manager

Go to the Navigation Menu and click it. Open the side panel and Go to the APIs and services Click it and go to click Credentials.

Step 02

APIs

Picture 04: The Path in Credentials

Step 03. Now you can see my exciting project “Student Management System”.

Student Management System

Picture 05: Download The path in Credentials

Click on the Download icon and get your OAuth client ID credentials in a JSON file. Go to the API Key Click on the SHOW KEY button. And copy the API KEY.

API Key

Picture 06: Open the API KEY popup window and copy the API KEY.

Successfully we get the API key and Credentials.

03. Apply the MERN stack

Above I shortly explain what the MERN stack is. Now I will apply Google OAuth how to work in the MERN stack. You can see this diagram.

Google OAuth

Picture 07: See the integration of Google OAuth2 API, Node.js, Express, Passport, MongoDB, and other packages

To implement Google OAuth in a MERN stack application, first, integrate Google OAuth in the React front end using @react-oauth/google to handle the authentication flow. Wrap your application with GoogleOAuthProvider and use the GoogleLogin component to prompt users to sign in. On successful login, retrieve the user token and send it to the Node.js backend via an API request. In the Node.js server, verify the token using the Google API and extract the user information. Then, check if the user exists in the MongoDB database; if not, create a new user record. Finally, generate a session token for the authenticated user and manage it on the client side for subsequent requests.

I will explain our project structure.

  1. REACT
  2. NODE and EXPRESS
  3. MONGODB

04. React application
 

04.1 Create the New React application.

Now I’m going to create a new React project.

Step 01. Go to the Command Prompt “ CMD Open the CMD and follow this command.

npx create-react-app google-oauth-mern/gui

Step 02. Move to the client folder cd google-oauth-mern and cd gui folder.

Client folder

Picture 08: Move to the GUI folder.

Open the terminal and type the ‘npm start’ command. Press the enter key.

Command

Picture 09: See the view

We successfully installed React JS and ran it. We are now implementing Google Auth in React.js by installing the necessary packages.

04.2 Install the Required Packages

To implement Google Auth in React.js, we need to install the following packages.

  1. @react-oauth/google: Google OAuth2 using the new Google Identity Services SDK
  2. Axios: Promise-based HTTP client for the browser and node.js
  3. Jwt-decode: JSON Web Token can be decoded.
npm install @react-oauth/google axios jwt-decode

JSON Web Token

Picture 10: We installed the necessary packages

Necessary packages

Picture 11: We check package.json package is installed or not

04.3 Create the login logout pages

Now have to create a folder as a Google-OAuth, inside of the folder create login and logout pages.

Logout pages

Picture 12: We create Login and Logout pages

Login page

import React from "react";
export default function Login() {
  return (
    <div>
      <button type="button">Login</button>
    </div>
  );
}

I'm going to integrate the login.jsx and logout.jsx pages into the app.js file.

04.4 Integrate the login.jsx and logout.jsx pages

import "./App.css";
import Login from "./google-Oauth/Login";
import Logout from "./google-Oauth/Logout";
function App() {
  return (
    <div className="App">
      <h1>Implementing Google OAuth in MERN</h1>
      <div className="center">
        <Login />
      </div>
      <div className="center">
        <Logout />
      </div>
    </div>
  );
}
export default App;

Mern

Picture 13: Go to run the app. And see the view in the browser

Now we want to create the env file for sensitive information

04.5 Create the env file

The .env file in a React and Node.js application is used to store environment variables, which are configuration settings that your application needs to run. These variables can include sensitive information like API keys, database connection strings, or any other configuration parameters specific to the environment where the application is running.

Let's create an env file.

  1. Go to the dotenv npm page. Install the npm package for dotenv for your node js application.
  2. Create an env file in reactjs/ node-js. Do not create a js file. Name it .env.

Go to the Client project, create the ‘.env’ file and add Client-Id and API-key

The process for obtaining the OAuth client ID and API key is already explained in pictures 5 and 6.

OAuth client ID

Picture 14: Add the client ID and API key

04.6 Create the Google Login

We can create the Google login by referring to this page: React OAuth2 | Google. We have already installed @react-oauth/google.

import React from "react";
import {GoogleOAuthProvider,GoogleLogin,googleLogout} from "@react-oauth/google";
import { jwtDecode } from "jwt-decode";
const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
export default function login() {
  const handelLogin = (googleData) => {
    const userData = jwtDecode(googleData);
    console.log("userData====>",userData);
  };
  return (
    <div className="App">
      <button type="button">
        <GoogleOAuthProvider clientId={CLIENT_ID}>
          <GoogleLogin
            onSuccess={(credentialResponse) => {
              handelLogin(credentialResponse.credential);
            }}
            onError={() => {}}
          />
        </GoogleOAuthProvider>
      </button>
    </div>
  );
}

Now I'm going to explain the code step by step.

<GoogleOAuthProvider clientId={Your_CLIENT_ID}>
          <GoogleLogin
            onSuccess={(credentialResponse) => {
              handelLogin(credentialResponse.credential);
            }}
            onError={() => {}}
          />
        </GoogleOAuthProvider>
  1. GoogleOAuthProvider: This is a component from the @react-oauth/google library that wraps around your application or a part of your application where you want to enable Google OAuth2 authentication.
    <GoogleOAuthProvider clientId={CLIENT_ID} />
  2. This component wraps the Google login functionality and takes a clientId prop, which is your Google OAuth client ID.
    <GoogleLogin />
  3. GoogleLogin: This component renders a Google login button
  4. onSuccess: This prop specifies a callback function that gets called when the login is successful. It receives a credentialResponse object, from which you can extract the user's credential and pass it to the handle login function.
    const handelLogin = (googleData) => {
        const userData = jwtDecode(googleData);
        console.log(userData);
      };
    
  5. handleLogin: This is a function that handles the Google login data.
  6. googleData: This parameter represents the credential data received from Google after a successful login.
  7. jwtDecode: This function (usually from a library like jwt-decode) decodes the JSON Web Token (JWT) contained in googleData.
  8. userData: This variable holds the decoded user information extracted from the JWT.
  9. console.log(userData): This line logs the decoded user information to the console.

Now, we can run the application.

Run the application

Picture 15: See the view Google login button and logout button available

Click on the “Sign in with Google” Button.

Sign in with Google

Picture 16: See the view Google login available

Gmail account

Picture 17: Login with a Gmail account

Get the console output of userData here.

UserData

Picture 18: Now you can see the login information here

Successfully we get the Goole OAuth token. retrieve the user token and send it to the Node.js backend via an API request.

04.6.1 Initialization of State

const [loginData, setLoginData] = useState(
    localStorage.getItem("loginData")
      ? JSON.parse(localStorage.getItem("loginData"))
      : null
  );

Your state is initialized correctly, checking if loginData exists in local storage. If it does, it parses and uses it; otherwise, it sets the state to null.

04.6.2 Define the handleLogin Function

const handelLogin = async (googleData) => {
    //const userData = jwtDecode(googleData);
    try {
      const res = await fetch("http://localhost:5000/api/google-login", {
        method: "POST",
        body: JSON.stringify({token: googleData, }),
        headers: { "Content-Type": "application/json" },
      });
      if (!res.ok) {
        throw new Error("Failed to log in with Google");
      }
      const data = await res.json();
      setLoginData(data);
      localStorage.setItem("loginData", JSON.stringify(data));
    } catch (error) {
      console.error("Error logging in:", error);
    }
  };
  • The function handleLogin takes googleData as an argument, which contains the Google authentication data.
  • It makes a POST request to the server with the googleData token.
  • If the response is not OK, it throws an error.
  • If the response is successful, it parses the JSON response, updates the state with the received data, and stores this data in localStorage.
  • If an error occurs at any point, it logs the error to the console.

Login.jsx Pages code

import React from "react";
import {
  GoogleOAuthProvider,
  GoogleLogin,
  googleLogout,
} from "@react-oauth/google";
import { jwtDecode } from "jwt-decode";
const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
export default function login() {
  const [loginData, setLoginData] = useState(
    localStorage.getItem("loginData")
      ? JSON.parse(localStorage.getItem("loginData"))
      : null
  );
  const handelLogin = async (googleData) => {
    //const userData = jwtDecode(googleData);
    try {
      const res = await fetch("http://localhost:5000/api/google-login", {
        method: "POST",
        body: JSON.stringify({token: googleData, }),
        headers: { "Content-Type": "application/json" },
      });
      if (!res.ok) {
        throw new Error("Failed to log in with Google");
      }
      const data = await res.json();
      setLoginData(data);
      localStorage.setItem("loginData", JSON.stringify(data));
    } catch (error) {
      console.error("Error logging in:", error);
    }
  };
  return (
    <div className="App">
      <button type="button">
        <GoogleOAuthProvider clientId={CLIENT_ID}>
          <GoogleLogin
            onSuccess={(credentialResponse) => {
              handelLogin(credentialResponse.credential);
            }}
            onError={() => {}}
          />
        </GoogleOAuthProvider>
      </button>
    </div>
  );
}

We will create the Node.js backend.

05. Node.js backend application

In my previous article, I provided a step-by-step guide on Setting up the Node.js Environment and Running a Simple Node Server Project. If you're new to Node.js, I recommend reading that article first for detailed instructions. Once you're familiar with the setup, return to this article for further insights.

05.1. Create the Node.js application.

Now I’m going to create a new folder as an API and inside of the folder open the terminal and type npm init -y.

To install an npm package, go to the terminal and type npm init -y. This command initializes a new npm project with default settings, skipping the prompts that npm init would normally display. During the standard npm init process, you'll be asked several questions, including the package name. You can specify your own package name, or it will default to the name of the project folder. By using the -y flag, npm init -y automatically sets the package name to the default project folder name without prompting you for input.

Default project folder

Picture 19: Now you can see the \package.json info here

05.1. Install NPM Packages

Install the necessary npm packages: Express, nodemon, body-parser, and Mongoose. These packages are essential for working with API projects. Here are the details of each package.

  • Express: A web application framework for Node.js that simplifies building and managing web applications.
  • Body-parser: A middleware for Node.js that parses incoming request bodies in a middleware before your handlers, making it easier to handle form submissions and JSON payloads.
  • Nodemon: A utility that automatically restarts your Node.js application when file changes in the directory are detected, streamlining development and testing.
  • Mongoose: An object data modeling (ODM) library for MongoDB and Node.js, providing a straightforward, schema-based solution to model your application data.

To install these packages, run the following command in your project directory.

npm install express nodemon body-parser mongoose

Project directory

Picture 20: You can see the dependencies here. I installed express, body-parser, nodemon, and Mongoose npm packages

05.2. Create index.js

Create an Index page index.js.

const express = require("express");
const app = express();
app.get("/", function (req, res) {
  res.send("Hello C# Corner.");
});
app.listen(3000);

1. Import the Express module

const express = require("express");

This line imports the Express module, which is a web framework for Node.js. express will be used to create an Express application.

2. Create an Express application

const app = express();

This line creates an instance of an Express application.

3. Define a route for GET requests to the root URL ("/")

app.get("/", function (req, res) {
  res.send("Hello C# Corner.");
});

It has a callback function (req, res) req = it listens to the incoming request object, and res = responds accordingly using the response object.

4. Start the server and listen on port 3000

app.listen(3000);

It listens for incoming requests on port 3000. Once the server is running, it will be accessible via http://localhost:3000.

5. Config Script package.json

Add the line start script from package.json.

"scripts": {
  "start": "nodemon index.js"
}

run the node js “npm start”.

Npm start

Picture 21: You can see that this runs the node js “npm start”. App listen 5000, script running nodemon index.js

Verify the response body using Postman at localhost port 5000.

Postman

Picture 22: You can see this GET method call, which returns the message 'Hello C# Corner.' with a status of success (200 OK)

06. Get the MongoDB Connection String

Creating a MongoDB Atlas Account and Establishing a MongoDB Connection.

If you're looking to create a MongoDB Atlas account and set up a MongoDB connection, I've got you covered. I’ve detailed these processes in my previous articles, which you can find linked below.

How to Create a MongoDB Atlas Account?

For a step-by-step guide on creating a MongoDB Atlas account, check out my article: How to Create a MongoDB Atlas Account.

Node.js RESTful API Project with Express, MongoDB, and Postman.

To learn how to build a Node.js RESTful API project using Express, MongoDB, and Postman, refer to my detailed guide here: Node.js RESTful API Project with Express, MongoDB, and Postman.

Here is the link. Please read it; I will continue with this article.

Go to the MongoDB cluster on the dashboard.

MongoDB cluster

Picture 23: Click on the "Connect" button in the cluster on the dashboard

DB Connection

DB Connection

Picture 24: Click on the "Drivers" tab in the dashboard

  • Open the MongoDB Driver.
  • Select your driver and version.
  • Copy your connection string to your application code.

MongoDB Driver

Picture 25. 01: You will select your driver with the version. 02. You can copy the Connection string

07. Connect the API with MongoDB
 

07.1. Create the API env file

Now I'm going to create the env file. In this article, I explain the process under the heading '04.5 Create the env file'. Follow these steps:"

MONGO_DB=mongodb+srv://<Username>:<Password>@<clusterName>.joofg8v.mongodb.net/<your_database_name>?retryWrites=true&w=majority

Now I'm going to create the DB as a “GoogleOAuth”. Env file mongoDB variable set DB name.

MONGO_DB=mongodb+srv://<Username>:<Password>@<clusterName>.joofg8v.mongodb.net/GoogleOAuth?retryWrites=true&w=majority

Env file

Picture 26: You can see the env setup MONGO_DB and PORT

You can pass your MongoDB connection string in MONGO_DB in env.

07.2. DB Connection Check

Check whether the DB connection is successful or not.

require("dotenv").config();
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const MONGO_DB = process.env.MONGO_DB;
const PORT = process.env.PORT;
app.get("/", function (req, res) {
  res.send("Hello C# Corner.");
});
mongoose
  .connect(MONGO_DB)
  .then(() => {
    console.log("connected to MongoDB");
    app.listen(PORT, () => {
      console.log(`Node API app is running on port ${PORT}`);
    });
  })
  .catch((error) => {
    console.log(error);
  });
const mongoose = require("mongoose");

This line imports the Mongoose library, which is an Object Data Modeling (ODM) library for MongoDB and Node.js.

Load Environment Variables

const MONGO_DB = process.env.MONGO_DB;
const PORT = process.env.PORT;

These lines load the MongoDB connection string (MONGO_DB) and the port number (PORT) from environment variables.

Connect to MongoDB

mongoose
  .connect(MONGO_DB)
  .then(() => {
    console.log("connected to MongoDB");
    app.listen(PORT, () => {
      console.log(`Node API app is running on port ${PORT}`);
    });
  })
  .catch((error) => {
    console.log(error);
  });

mongoose.connect(MONGO_DB): This attempts to connect to the MongoDB database using the connection string stored in the MONGO_DB environment variable. It returns a promise. If the connection is successful, the callback function inside then is executed.

.catch((error) => { ... }): If the connection fails, the callback function inside catch is executed.

Connection fails

Picture 27: Successfully connected to the database

07.3. Verify the token using the Google API

  1. Verify the token using the Google API.
  2. Extract the user information.
  3. Check if the user exists in the MongoDB database; if not, create a new user record.
  4. Generate a session token for the authenticated user.

MongoDB database

Picture 28: Verify the token and Check if the user exists in the MongoDB database; if not, create a new user record

07.4. Create a Model for Data in the Database

  1. Create a new folder as models.
  2. Create a userModel.js page. And Continue this code.

Continue this code

Picture 29: You can see this usermodel

Here I can share userModel.js.

const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
    googleId: { type: String, required: true, unique: true },
    email: { type: String, required: true },
    name: { type: String, required: true },
    picture: { type: String }
});
module.exports = mongoose.model('User', userSchema);

This defines the structure of a user document with four fields.

  • googleId: A unique identifier from Google (string, required, unique).
  • email: The user's email (string, required).
  • name: The user's name (string, required).
  • picture: The URL of the user's profile picture (string).

07.5. Add the client ID and Google API key in env

The process for obtaining the OAuth client ID and API key is already explained in pictures 5 and 6.

I explain the process under the heading '07.1 Create the API env file'. Follow these steps."

  1. REACT_APP_GOOGLE_CLIENT_ID =
  2. REACT_APP_GOOGLE_API_KEY=

07.6. Install NPM Packages

  1. ( Google Auth Library: Node.js, jsonwebtoken, and Cors)
  2. Installing Google Auth Library: Node.js Client This is the officially supported Node.js client library by Google for using OAuth 2.0 authorization and authentication with Google APIs.
    npm i google-auth-library
  3. Jsonwebtoken is a library in Node.js used to create, sign, and verify JSON Web Tokens (JWTs). JWTs are a compact, URL-safe means of representing claims between two parties. They are often used for authentication and secure information exchange.
    npm i jsonwebtoken
  4. CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
    npm i cors

07.7. Create a Google Login Endpoint

const CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const JWT_SECRET = process.env.JWT_SECRET;
const client = new OAuth2Client(CLIENT_ID);
app.use(express.json());
app.use(cors({ origin: "http://localhost:3000" }));
app.post("/api/google-login", async (req, res) => {
  const { token } = req.body;

  try {
    // Verify the token using Google API
    const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,
    });

    const payload = ticket.getPayload();
    const { sub, email, name, picture } = payload;

    // Check if the user exists in the MongoDB database
    let user = await User.findOne({ googleId: sub });

    if (!user) {
      // Create a new user record if not exist
      user = new User({
        googleId: sub,
        email,
        name,
        picture
      });
      await user.save();
    }

    // Generate a session token for the authenticated user
    const sessionToken = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });

    // Send the session token to the client
    res.json({ success: true, sessionToken });
  } catch (error) {
    console.error('Error verifying token:', error);
    res.status(401).json({ success: false, message: 'Invalid token' });
  }
});

01. Initialize OAuth2 Client

const client = new OAuth2Client(CLIENT_ID);

Prepares the Google OAuth2 client for token verification.

02. Middleware Setup

app.use(express.json());
app.use(cors({ origin: "http://localhost:3000" }));

Configures Express to parse JSON and handle CORS for requests from.

Google Login Endpoint

app.post("/api/google-login", async (req, res) => {
  const { token } = req.body;
  try {
    // 01. Verify the token using Google API
    const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,
    });
    const payload = ticket.getPayload();
    const { sub, email, name, picture } = payload;
    // 02. Check if the user exists in the MongoDB database
    let user = await User.findOne({ googleId: sub });
    if (!user) {
      // 03. Create a new user record if not exist
      user = new User({
        googleId: sub,
        email,
        name,
        picture
      });
      await user.save();
    }
    // 04. Generate a session token for the authenticated user
    const sessionToken = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });
    // 05. Send the session token to the client
    res.json({ success: true, sessionToken });
  } catch (error) {
    console.error('Error verifying token:', error);
    res.status(401).json({ success: false, message: 'Invalid token' });
  }
});

Google Login Endpoint: Handles the /API/google-login route to.

  1. Verify the Google token.
  2. Extract user information.
  3. Check or create a user in MongoDB.
  4. Generate a session token.
  5. Send the session token back to the client.

08. Run the Application

Go to the GUI folder, open the terminal in your VS Code, and run this command: npm start. The same command applies to the API folder as well.

 API folder

Picture 30: Run this command GUI and API: npm start

React App

Picture 31: Click on the “Sign in with Google” Button

Implementing

Picture 32: Login in your email

Login Email

Picture 33: See the network tab API call “google-login”. Status 200

Successfully Make the API Call

  1. Implement the API call as described in the code.
  2. In your browser, open the Developer Tools (usually by pressing F12 or right-clicking and selecting "Inspect").
  3. Go to the "Network" tab.
  4. Trigger the Google login process in your application.
  5. Look for the network request named "google-login" in the Network tab.
  6. Ensure that the status of this request is 200, indicating a successful API call.

09. View the Database

Go to the MongoDB cluster on the dashboard.

  1. Click on the Database Button and
  2. Click on your cluster.

Clusters

Picture 34: Click on the cluster

After you get the cluster dashboard, Click on the Collections tab.

Collections tab

Picture 35: Click on the Collections tab

DB dashboard registered user

Picture 36: See the DB dashboard registered user details here

10. View the Login Data in the GUI

Successfully made the API call as explained in Picture 33. Check the network tab for the API call 'google-login' with status 200. And we get the response from API " loginData.sessionToken". we modify the code by the session token.

10.1 Update user state

 const [user, setUser] = useState({});
  useEffect(() => {
    if (loginData) {
      const decodedUser = jwtDecode(loginData.sessionToken);
      setUser(decodedUser);
    }
  }, [loginData]);
const [user, setUser] = useState({});

Initializes a state variable user with an empty object {} using useState.

useEffect(() => {
  // Your code here
}, [loginData]);

Runs the code inside the useEffect callback function when login data changes.

Inside the useEffect callback

  • Check if loginData is true.
  • Decodes the sessionToken from loginData using jwtDecode.
  • Updates the user state with the decoded user object (decodedUser).
<div className="App">
      {loginData ? (
        <>
          <div>
            <img src={user.picture} alt={user.userName} />
            <h3>{user.email}</h3>
            <h6>{user.userName}</h6>
          </div>
          <div>
            <button onClick={handelLogout}>Logout</button>
          </div>
        </>
      ) : (
        <div className="App">
          <button type="button">
            <GoogleOAuthProvider clientId={CLIENT_ID}>
              <GoogleLogin
                onSuccess={(credentialResponse) => {
                  handelLogin(credentialResponse.credential);
                }}
                onError={() => {}}
              />
            </GoogleOAuthProvider>
          </button>
        </div>
      )}
    </div>

The code conditionally renders different content based on the presence of loginData. If loginData is present, it shows the user's profile picture, email, and username, along with a logout button that triggers the handelLogout function. If loginData is not present, it shows a Google login button using the GoogleOAuthProvider and GoogleLogin components. The GoogleLogin component handles the login process, triggering the handelLogin function on success, while the onError prop is left empty.

OnError prop

Picture 37: Successfully log in and view the user details

10.2 HandeLogout function

const handelLogout = () => {
    setLoginData(null);
    localStorage.removeItem("loginData");
    googleLogout();
  };
setLoginData(null);

Sets the state variable loginData to null. This likely indicates that the user is no longer logged in, as null typically represents the absence of a logged-in state.

localStorage.removeItem("loginData");

Removes the item with the key "loginData" from the browser's localStorage. This is likely used to clear any persisted login data stored locally, ensuring the user isn't automatically logged back in on subsequent visits.

googleLogout();

It calls a function googleLogout() that presumably handles logging users out of a Google-related service or OAuth session.

Google-related service

Picture 38: Successfully Logout

Full Code of login.jsx

import React, { useEffect, useState } from "react";
import {
  GoogleOAuthProvider,
  GoogleLogin,
  googleLogout,
} from "@react-oauth/google";
import { jwtDecode } from "jwt-decode";
const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
export default function Login() {
  const [loginData, setLoginData] = useState(
    localStorage.getItem("loginData")
      ? JSON.parse(localStorage.getItem("loginData"))
      : null
  );
  const [user, setUser] = useState({});
  useEffect(() => {
    if (loginData) {
      const decodedUser = jwtDecode(loginData.sessionToken);
      setUser(decodedUser);
    }
  }, [loginData]);
  const handelLogin = async (googleData) => {
    try {
      const res = await fetch("http://localhost:5000/api/google-login", {
        method: "POST",
        body: JSON.stringify({ token: googleData }),
        headers: { "Content-Type": "application/json" },
      });

      if (!res.ok) {
        throw new Error("Failed to log in with Google");
      }
      const data = await res.json();
      setLoginData(data);
      localStorage.setItem("loginData", JSON.stringify(data));
    } catch (error) {
      console.error("Error logging in:", error);
    }
  };
  const handelLogout = () => {
    setLoginData(null);
    localStorage.removeItem("loginData");
    googleLogout();
  };
  return (
    <div className="App">
      {loginData ? (
        <>
          <div>
            <img src={user.picture} alt={user.userName} />
            <h3>{user.email}</h3>
            <h6>{user.userName}</h6>
          </div>
          <div>
            {" "}
            <button onClick={handelLogout}>Logout</button>
          </div>
        </>
      ) : (
        <div className="App">
          <button type="button">
            <GoogleOAuthProvider clientId={CLIENT_ID}>
              <GoogleLogin
                onSuccess={(credentialResponse) => {
                  handelLogin(credentialResponse.credential);
                }}
                onError={() => {}}
              />
            </GoogleOAuthProvider>
          </button>
        </div>
      )}
    </div>
  );
}

Summary

The article explores integrating Google OAuth into a MERN (MongoDB, Express.js, React.js, Node.js) stack application. It begins with an introduction to the MERN stack's components and benefits. The implementation of Google OAuth involves several key steps.

  1. Setting up Google OAuth credentials through the Google API Console.
  2. Integrating Google OAuth in a React frontend using @react-oauth/google for authentication.
  3. Handling user authentication and token exchange between the frontend and backend (Node.js).
  4. Verifying tokens using Google APIs and storing user information in MongoDB.
  5. Running and testing the integrated application, including setting up necessary environment variables and configuring API endpoints.

Throughout the article, detailed steps are provided for setting up both the frontend and backend components, ensuring a comprehensive guide to implementing Google OAuth in a MERN stack application.

I'm attaching the GitHub project link here. https://github.com/navamayoo/google-oauth-mern


Similar Articles
Orfium Sri Lanka
Globally based Software Developing & Data Processing Company