Google Authentication in Nodejs using Passport and Google Oauth
Tags: javascript, node, webdev, google
Published: 2024-04-23 17:07:05

Google authentication is one of the seamless and fastest modes of authenticating users in an application. It saves the user the time of filling out forms with his/her details and verifying email addresses.

In this article, we will implement Google authentication in our NodeJS application.

### Create Your NodeJS Application

* **Install Node.js**

    You should have Nodejs installed on your laptop and if not, check the [Node.js official website](https://nodejs.org/), and download/ install the latest and stable release.
    
    To verify if node.js was successfully installed, paste the command below on your Command Line Interface (CLI) to check the version of node.js installed.
    

    ```javascript
    // terminal
    node --version
    ```
    
* **Set up a simple Node.js app**
    
    Create a directory for your application, I will create mine on the desktop using the CLI. I am using the Windows operating system and VS Code editor.
    
    ```javascript
    // terminal 
    cd desktop 
    mkdir my-nodejs-app //create a project directory
    cd my-nodejs-app // navigate to the app directory
    npm init -y // create a default package.json file
    npm install express dotenv passport passport-google-oauth20 express-session // install necessary dependencies
    code . // to open the directory on my code editor (VS Code). You can do it manually.
    ```
    
* **Modify package.json file**
    
    Configure the JSON file to get connected to the server.js file, for the application to use the ECMAScript 6 (ES6) modules, and to run a development server using the `--watch` flag.
    
    ```javascript
    //package.json
    {
      "name": "my-nodejs-app",
      "version": "1.0.0",
      "description": "",
      "type": "module", // add this to use the ES6 
      "main": "server.js", // update this to 
      "scripts": {
        "dev": "node --watch server.js" // script to run a development server
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "dotenv": "^16.4.5",
        "express": "^4.19.2",
        "express-session": "^1.18.0",
        "passport": "^0.7.0",
        "passport-google-oauth20": "^2.0.0"
      }
    }
    ```
    

* **Create the Server**
    
    Create an `server.js` file in the base of the directory to set up our project server.
    
    ```javascript
    // server.js
    
    // import necessary depenencies
    import "dotenv/config";
    import express from "express";
    import passport from "passport"; 
    import { Strategy as GoogleStrategy } from "passport-google-oauth20";
    import session from "express-session";
    
    // intialize app and define the server port
    const app = express();
    const port = process.env.PORT || 8000;
    
    // a middleware to access json data
    app.use(express.json());
    
    // a view to check if the server is running properly 
    // check `http://127.0.0.1:${port}/` -> http://127.0.0.1:800
    app.get("/", (req, res) => {
      res.send(`My Node.JS APP`);
    });
    
    // a function to start the server  and listen to the port defined
    const start = async () => {
      try {
        app.listen(port, () => console.log(`server is running on port ${port}`));
      } catch (error) {
        console.log(error);
      }
    };
    
    // call the function
    start();
    ```
    
* **Generate a Google client Oauth credentials**
    
    You have to generate a Google client Oauth credentials(Client ID and Secret), if you are new to this, check out [tutorials](https://www.youtube.com/results?search_query=How+to+create+Google+OAuth+Credentials) on how to go about it.
    
* **Create a**`.env`**file**
    
    Make sure `dotenv` dependency is installed and imported into your `server.js` file. Use the format below to set the .env file.
    
    ```javascript
    //.env
    // make sure these values are correct
    GOOGLE_CLIENT_ID= // your google client id
    GOOGLE_CLIENT_SECRET= // your google client client
    SESSION_SECRET= // any randome secure characters
    PORT= 8000 // define port from the env file
    ```
    
* **Create**`passport.js`**file**
    
    Create an `utils` folder in the project directory base and create `passport.js` file. This is where the connection of our Node.js app to the Google Oauth App created on the Google console takes place.
    
    ```javascript
    // utils/passport.js
    
    // import necessary dependencies
    import passport from "passport";
    import { Strategy as GoogleStrategy } from "passport-google-oauth20";
    
    
    //initialize 
    passport.use(
      new GoogleStrategy(
        {
            
          clientID: process.env.GOOGLE_CLIENT_ID, // google client id
          clientSecret: process.env.GOOGLE_CLIENT_SECRET, // google client secret
          // the callback url added while creating the Google auth app on the console
          callbackURL: "http://localhost:8000/auth/google/callback", 
          passReqToCallback: true,
        },
    
    // returns the authenticated email profile
     async function (request, accessToken, refreshToken, profile, done) {
     // you can write some algorithms here based on your application models and all
     // an example - not related to this application
    
    /*
       const exist = await User.findOne({ email: profile["emails"][0].value });
       if (!exist) {
            await User.create({
            email: profile["emails"][0].value,
              fullName: profile["displayName"],
              avatar: profile["photos"][0].value,
              username: profile["name"]["givenName"],
              verified: true,
            });
          }
        const user = await User.findOne({ email: profile["emails"][0].value });
     return done(null, user);
    */
         return done(null, profile);
        }
      )
    );
    
    // function to serialize a user/profile object into the session
    passport.serializeUser(function (user, done) {
      done(null, user);
    });
    
    // function to deserialize a user/profile object into the session
    passport.deserializeUser(function (user, done) {
      done(null, user);
    });
    ```
    
* Update the `server.js`
    
    The application session(middleware) must be initialized and configured to Google passport. The route for the authentication and the callback needs to be defined.
    
    ```javascript
    // server.js
    
    // import necessary depenencies
    import "dotenv/config";
    import express from "express";
    import passport from "passport";
    import session from "express-session";
    // import passport.js
    import "./utils/passport.js"
    
    // intialize app and define the server port
    const app = express();
    const port = process.env.PORT || 8000;
    
    // a middleware to access json data
    app.use(express.json());
    
    // use the session middleware
    app.use(
      session({
        secret: process.env.SESSION_SECRET, // session secret
        resave: false,
        saveUninitialized: false,
      })
    );
    
    // initialize passport and session
    app.use(passport.initialize());
    app.use(passport.session());
    
    
    // a view to check if the server is running properly
    app.get("/", (req, res) => {
      res.send(`My Node.JS APP`);
    });
    
    // authetication route
    app.get(
      "/auth/google",
      passport.authenticate("google", {
        scope: ["email", "profile"],
      })
    );
    
    // Call back route
    app.get(
      "/auth/google/callback",
      passport.authenticate("google", {
        access_type: "offline",
        scope: ["email", "profile"],
      }),
      (req, res) => {
        if (!req.user) {
          res.status(400).json({ error: "Authentication failed" });
        }
        // return user details
        res.status(200).json(req.user);
      }
    );
    
    
    // a function to start the server  and listen to the port defined
    const start = async () => {
      try {
        app.listen(port, () => console.log(`server is running on port ${port}`));
      } catch (error) {
        console.log(error);
      }
    };
    
    // call the start function
    start();
    ```
    

### Test your Node.JS Application

* **Run server(dev)**
    
    Based on the custom configuration in the package.json file, to run the development use the command `npm run dev`
    
* **Authenticate a user**
    
    Click this link [http://127.0.0.1:8000/auth/google](http://127.0.0.1:8000/auth/google) if your server is running on port 8000. You should see a page like the one below.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713543755636/6442dd16-b3cf-4047-99c8-ea42cc5f75f8.png align="center")
    
    After selecting an email address, it should return JSON data of that particular account.
    

### **Conclusion**

I hope you found the article helpful and were able to implement the Google authentication in your Node.js application. You can check out the [tutorial source code](https://github.com/chryzcode/google-auth-node-tutorial).

If yes, do well to like and share this piece and comment with me on [**Linkedin**](https://www.linkedin.com/in/olanrewaju-alaba/), [**Twitter**](https://twitter.com/chryzcode) and [**GitHub**](https://github.com/chryzcode). And if you like what you read and want to show support, you can [**buy me coffee😉**](https://www.buymeacoffee.com/chryzcode).