Google OAuth in Nodejs, Express, and Reactjs
In this article, I will walk you through implementing google OAuth with passportjs and JWT in a React, Node, Express, Sequelize, and PostgreSQL application. The same flow can be used on a Next.js application as well.
Originally published at https://awacreates.com.
What is Google Oauth?
Oauth stands for Open Authorization. It allows third-party services like Google and Facebook to exchange your information without you having to give away your passwords. This helps prevent your password from being compromised. Learn more about Google Oauth here.
How does Google Oauth work?
Once a user clicks on the Oauth login button, our frontend sends a request to the Google authorization server through a browser redirect and obtains an access token that will grant access to the Google API. During the access-token request, our application sends one or more values in the scope parameter which controls the set of resources and operations that an access token permits.
After obtaining the access token, what happens next?
Our application makes a call to the Google API, setting the token in the HTTP Authorization request header. The access token will be valid only for the set of operations and resources described in the scope of the token request.
Our request is authenticated using passport.js authentication and sends the user’s profile info. We will receive the user’s profile info inside a passport verify callback whose purpose is to find the user that possesses the set of credentials.
Once authentication is successful, a session is established and maintained via a cookie set in the user’s browser. Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. Passport uses the serialize and deserialize functions to save the user’s ID to and from the session.
Google Oauth Flow diagram
Understanding passport Serialize and Deserialize functions
- serializeUser: Determines which data of the user object should be stored in the session. The result of the serializeUser method is attached to the session as req.session.passport.user
- In our case only the user ID will be serialized to the session, keeping the amount of data stored within the session small.
- deserializeUser: Used to retrieve the id stored in the session by the serializeUser function. This is where we make a backend call to get the user instance by that ID and attach it to the request object as req.user.
Visit http://www.passportjs.org/docs/configure/ for more info about serializeUser and deserializeUser functions.
After deserializing, our next handler receives control, generates a JWT token from the credentials in req.user, and sends a response containing the user’s object and the JWT.
Feel free to comment if there’s anything you do not understand about the above explanations.
Implementing Google Oauth in Nodejs, express, sequelize, and Postgres
1. Create a Google client ID and client secret
Visit Google API Console and obtain OAuth 2.0 credentials such as a client ID and client secret that will be known to both Google and our application.
Below are the steps to follow:
- From the projects drop-down, create a new one by clicking on New project.
- In the sidebar under “APIs & Services”, select Credentials
- In the Credentials tab, click the Create credentials drop-down list, and choose OAuth client ID.
- Configure the consent screen and set the scopes. When you’re done, go back to the dashboard.
- Click again on Create credentials drop-down list, and select OAuth client ID, but this time it will take you to a page where you will select the application type. Choose Web application.
- Under Authorised JavaScript origins, enter the backend API’s URL, which in our case is going to be http://localhost:3000
- Under Authorised redirect URIs, enter the frontend URL which is going to be: http://localhost:4000, and click save.
2. Initialize Nodejs and install all dependencies
Create an empty folder and open it in your favorite editor. Run the following to initialize a Nodejs project.
npm init
After that is complete, run the following to install all necessary dependencies
npm i body-parser cors dotenv express jsonwebtoken passport passport-google-token pg sequelize
Install Dev dependencies
npm i --save-dev @babel/cli @babel/core @babel/node @babel/plugin-proposal-optional-chaining @babel/plugin-transform-runtime @babel/preset-env @babel/register @babel/runtime babel-node nodemon sequelize-cli
3. Configure Express server
// api/server.js
import cors from 'cors';
import logger from 'morgan';
import express from 'express';
import bodyParser from 'body-parser';const app = express();app.use(cors({ origin: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(logger('dev'));const port = process.env.PORT || 5000;app.listen(port, () => console.log(`Server running on http://localhost:${port}`));
4. Setup Postgres database connection with Sequelize
Step 1: Create a .sequelizerc file with the following code
Step 2: Initialize sequelize
sequelize init
This will create the following folders
- config.js, which tells the Sequelize CLI how to connect to the database
- models contain all models for your project
- migrations contain all migration files
- seeders contain all seed files
Step 3: Configure Postgres database connection
Let’s start by creating our .env file to store our environment variables such as our google client key, JWT secret, Database connection URL, …etc
Copy the Google Client Id and Secret Id from your Google API Console dashboard and save them inside the .env file.
DATABASE_DEV=postgres:
GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= JWT_SECRET=
Copy and paste the following connection setup code inside config.js file.
This file is supposed to set up a connection to our database, but we do not have one yet. So run the following sequelize command to create the database for our API
sequelize db:create
Step 4: Create a migration file for the users’ table
Now that we are done with the configurations, let’s create the users’ migration file with all its columns by running the following command:
sequelize model:generate --name User --attributes name:string,email:string,password:string,goodleId:string,provider:string
As soon as this is done running, let us create the database table by executing the migration as follows:
sequelize db:migrate
5. Create Google Oauth endpoint
Step 1: Configure passport.js and google strategy:
Create a controller folder in the /api directory and create another new folder for authController with index.js and passport.js in it.
Copy and paste the following code into the passport.js file you just created.
So we imported our google strategy and created an instance of it inside the use() function. Inside the verify callback we are getting the user’s profile coming from google to check if that user already signed up through Google Oauth, else we sign him up and call done(null, user).
Step 2: Create a controller function for completing the OAuth flow:
Inside our controller/index.js file, copy and paste the following code
What this google OAuth does is to receive the authenticated user from the req object generate a JWT token and return a response of the user and his login token.
Step 3: Connect passport.js configurations to the server and add a route:
Import the configurations from controllers/passport.js inside our express server and create the endpoint for Google OAuth. The server should now look like this:
And then we are done with Implementing Google Oauth in Nodejs, express, sequelize, and Postgres. Let’s go ahead and consume the OAuth endpoint on the frontend.
Implementing Google Oauth in ReactJs
1. Initialize create-react-app:
Initialize a new react project by running the following in your term
npx create-react-app google-oauth-client
2. Install all necessary dependencies:
npm i --save axios react-google-login js-cookie
3. Use GoogleLogin button component from react-google-login:
Let’s first of all setup our environment variables.
Create a .env file in the root directory of the application and add the following variables to it.
REACT_APP_API_BASE_URL=http: REACT_APP_GOOGLE_CLIENT_ID=
Inside our App.jsx component, copy and paste the following code
You should have something like this as the end result
Test it out, if you face any issues, let me know in the comment section, I am available 24/7 to answer your questions.
Conclusion
So that is it for setting up google OAuth. Now I’d like to hear what you have to say.
Have you learned something new? Drop it in the comment section, we never can tell how many people will learn from us. Was it helpful? Spread the word, share with friends even on social media.
Thanks
Originally published at https://awacreates.com.