DEV Community

mismathh
mismathh

Posted on

Integrating Google Authentication to Chat Application - Progress

As discussed in my last post, my current focus has been on implementing an alternative authentication method to log in into Chat Application. In this update, I wanted to share the progress I have made.

Integrating OAuth 2.0 and Google API with Passport.js

My initial thoughts to this step was that it was going to be more code heavy, but it ended being more to do with acquiring certain values from Google to be able to connect to the API.

In order to use Google authentication with OAuth 2.0, the relevant "Strategy" library is needed from the passport-google-oauth2 package. With that, we can use passport.use() to create our Strategy to be used when users log in with Google.

passport.use(
    new GoogleStrategy(
      {
        clientID: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        callbackURL: "http://localhost:3000/auth/google/callback",
      },
      authenticateGoogleUser
    )
  );
Enter fullscreen mode Exit fullscreen mode

To connect to the Google API, a clientID and clientSecret key is needed. The Google Cloud Platform is where you can acquire these values after creating a project to link with your application.

Front-end User Interface

I decided to create a simple button to provide the option for users to login with their Google accounts, and kept the dark tone to match the rest of the page.

Google Button

Back-end Routes

Two routes needed to be created to handle Google authentication requests. The /auth/google route will be called once the user clicks on the button to log/sign in with Google. This will redirect the user to the Google OAuth consent screen where they will need to choose a Google account to log in while accepting that some information from Google will be passed to the app.

In this case, the scope is what defines what information we are requesting from Google. There are many other values that may seem important to you, such as email, etc., but for the purpose of this app, the profile scope contains a unique id that we can store in our database to verify the user.

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

The second route will be called after we have verified and retrieved the information back from Google. If it was successful, it will redirect the user to the / page, and to the /login page if verifying the user was unsuccessful.

app.get('/auth/google/callback', passport.authenticate( 'google', {
    successRedirect: '/',
    failureRedirect: '/login'
 }));
Enter fullscreen mode Exit fullscreen mode

Passport Names

One of the hiccups I faced when implementing this alternative authentication, was the functionality of signing in through local or Google authentication, and to have both functional at the same time. Having multiple passport strategies places more importance on the name of the strategy, and to call the correct one for certain routes. I've only used the passport-local package in my projects thus far, and when trying to use authenticate(), the name of the strategy was always local, which made sense at the time. "The package is called passport-local so the name to use should be local." That kind of thought process won't work for passport-google-oauth2. I was planning to use a new name for the Google passport strategy, but I honestly got lucky, as I typed in "google" for the passport name and it worked, but where did this come from?

I did a little digging and found out that for each of these specific "Strategies" that you download, the default name is set within the strategy (or module) itself. When you require the the module, it exports a Strategy constructor function that sets the default name:

// Inside the passport-google-oauth2 module
OAuth2Strategy.call(this, options, verify);
  this.name = 'google';
Enter fullscreen mode Exit fullscreen mode

Therefore, if you are using multiple specific passport Strategies, instead of creating new names, you could also just look for the default name that is set within the module.

Pull Request

All these changes can be found in my PR, which currently needs to be reviewed first until it can be merged.

Top comments (0)