Express.js OAuth Google Authentication

This blog post will walk through an implementation of an OAuth 2.0 social authentication using Google social sing-in in an Express.js web application. Small disclaimer, this post assumes you've already registered a google application with your google developer account. The main concern of this post is connecting our express application with google's authorization.

Check out this example repo to see an implementation of what we review below. It contains a file structure that allows for a more modular codebase.

Create the required endpoints for OAuth

First, we need to create an login endpoint that our users can request to in order to initiate the OAuth process, this endpoint will ideally re-direct them to a Google sign in screen. This endpoint will be something akin to /v1/auth/google. You can and probably will be creating more endpoints for different OAuth providers as your application demands it.

Second we need to create the callback endpoint we agreed upon with whatever authorisation provider we selected. This endpoint will be something akin to /v1/auth/google/callback.

Third we need to create an endpoint for logging out. This endpoint is not specific to any authorisation provider and instead is a more generic function of your application. The endpoint will be something akin to /v1/auth/logout.

Note that all three of these endpoints will be GET requests. That is, app.get('/v1/auth/google/callback', (req, res) => ...) for example.

Use Passport.js for pre-built strategies

We could manually start implementing all the logic necessary for completing the OAuth process, but that wouldn't be very smart when we have Passport.js which is an authentication middleware bult for Node which allows us to select a strategy that will implement all that logic for us based on our needs.

In this example we are using OAuth 2.0 authentication with Google. Thus we search in the strategies searchbox for a package that has those requirements.

The package we want to install for an OAuth 2.0 Google authentication is passport-google-oauth20. We will also need to install the main passport package.

pnpm add passport passport-google-oauth20

Before any passport middleware initialization we must set the strategy that passport will use. At the top of our application we import our package and create an instance of the strategy we chose.

We pass it any options it needs through a config object and a verifyCallback function that it will use on every request asking for authentication.

import passport from "passport";
import { Strategy as OAuthGoogleStrategy } from "passport-google-oauth20";

const AUTH_OPTIONS = {
    callbackURL: "/v1/auth/google/callback",
    clientID: config.GOOGLE_CLIENT_ID,
    clientSecret: config.GOOGLE_CLIENT_SECRET,
    scope: ["email"]
};

function verifyCallback(
    accessToken: string,
    refreshToken: string,
    profile: any,
    done: any
) {
    console.log("Google profile", profile);
    done(null, profile);
}

passport.use(new OAuthGoogleStrategy(AUTH_OPTIONS, verifyCallback));

We also can't forget to initialize the passport middleware

let app = express();

app.use(passport.initialize());

We can now use the passport.authenticate() middleware in all of our relevant endpoints we defined before.

First we have our callback endpoint which is where our authorisation provider will send a request to

authRouter.get(
    "/google/callback",
    passport.authenticate("google", {
        failureRedirect: "/auth/google/failure",
        successRedirect: "/home",
    }),
    httpGoogleAuthCallback
);

Second, we also use the passport.authenticate() middleware in our login route. In here we once again specify to passport that we are using 'google' to authenticate. We also specify the scope of information we want to receive from the user.

authRouter.get(
    "/google",
    passport.authenticate("google"),
    httpGoogleAuth
);

Adding Sessions

We can combine Passport's sessions middleware with Express.js session's middleware to add sessions to our web application.