Section 31 – Lesson 407 – Complete 2020 Web Development Bootcamp

Lesson 407 – Level 6 OAuth 2.0 How to Implement Sign In with Google

OAuth stands for Open Authorisation.

OAuth is an open standard for token based authorisation.

Reasons to use OAuth –

  • It allows you to grant a granular level of access;
  • It allows for either Read only or Read/Write access;
  • It allows the third party that you are using to authenticate your users (for example – Facebook, Google, Amazon, LinkedIn, etc, to revoke access at any point on their website.

The first step in implementing OAuth is to set up your app in the third party’s (Facebook’s) developer console and get an app/client id.

The next step is that when a user tries to log on to your website, you give them an option to log on using the third party website (Facebook) and give them a link to take them to the third party website.

The user then logs in on the third party website (Facebook).

Once the user has logged in on the third party website (Facebook), they have to review the permission that your website is asking for. For example, you site might be asking for permission to access their profile and email address.

Once this has happened, your website will receive an authorization code from the third party website (Facebook) which allows your website to check whether the user logged onto the third party website.

Your site can they exchange the authentication code for an access token from the third party website. That access token would be saved in your database because you would use that access token to request pieces of information from the third party website.

In this lesson, you will be implementing log in with Google using Passport.js and Google OAuth.

The first step is to install the npm passport-google-oauth20 package by typing this in the terminal –

npm install passport-google-oauth20

The next step is to create an application on the Google Developers Console.

Then you create a new project named “Secret” in the Google Developers Console and set up the credentials for that project.

The next step is to create a constant variable GoogleStrategy in the app.js file like this –

const GoogleStrategy = require('passport-google-oauth20').Strategy;

Next you set up your GoogleStrategy. To do this the new code must be inserted below this code in the app.js file –

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

The new code is –

passport.use(new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/secrets",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
  },
  function(accessToken, refreshToken, profile, cb) {
    User.findOrCreate({ googleId: profile.id }, function (err, user) {
      return cb(err, user);
    });
  }
));

To make the “User.findOrCreate” portion of this code work, you have to install the npm mongoose-findorcreate package in the terminal with this code –

npm i mongoose-findorcreate

The next step is to require the mongoose-findorcreate package in the app.js file using this code –

const findOrCreate = require('mongoose-findorcreate');

You then have to add it as a plugin to your Schema using this code –

userSchema.plugin(findOrCreate);

The next step is to add buttons on the website to allow a user to login using Google.

This code is inserted in the register.ejs file and the login.ejs file to create a google button –

<div class="col-sm-4">
      <div class="card social-block">
        <div class="card-body">
          <a class="btn btn-block" href="/auth/google" role="button">
            <i class="fab fa-google"></i>
            Sign Up with Google
          </a>
        </div>
      </div>
    </div> 

Then you add an app.get{“/auth/google”) route like this –

app.get("/auth/google", 
	passport.authenticate("google", { scope: ['profile'] })
);

Next you have to create an app.get(“/auth/google/secrets”) route –

app.get("/auth/google/secrets", 
  passport.authenticate("google", { failureRedirect: "/login" }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect("/secrets");
  });

You then have to refactor the serialize/deserialize code to this –

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

Next you have to refactor our constant variable “userSchema” to create “googleId” as a piece of information that we will store. This is the refactored code –

const userSchema = new mongoose.Schema ({
	email: String,
	password: String,
	googleId: String
});