Google Authentication for NodeJS

2 min read

Google OAuth2 Authentication with NodeJS

Nothing makes me sweat like OAuth. Documentation is sparse and errors are cryptic. Libraries like Passport.js just add a poorly designed abstraction to an already difficult process. Does it have to be this hard? No.

Google authentication is actually pretty easy.

Google recently deprecated the old Google Plus API – so most google authentication guides are out of date. These days you’ll want to use the people.get endpoint.

Step 1. Get Credentials

First you need developer API credentials. Head over to the Google Developer Console and Create a New Project. Then go to your Project’s Dashboard and enable the Google People API. Now back to your project’s dashboard, click OAuth consent screen. Choose “External” and fill out the other info like website, company name, logo, etc.

Now go to the Credentials tab and click “Create Credentials > OAuth client ID”.

  • App Type – Choose “Website”
  • Authorized JavaScript origins – don’t include a path. For dev I use http://localhost:7777. For production use something like https://www.example.com
  • Authorized redirect URIs – This should include the full URL that google will send the user back to. For example http://localhost:7777/google/callback for dev or https://www.example.com/google/callback for prod.

You should now have your Client ID and Client Secret.

Step 2. Install googleapis

Congrats… the worst is over. Now you need to install the googleapis npm package.

npm install --save googleapis

Step 3. Setup The Google Connection

For these last 3 steps, we’ll create create a file (I’m calling it google-routes.js) that will contain the two expressjs routes for implementing google authentication.

At the top of google-routes.js, we’ll need to setup an auth object that has our client id, secret, and redirect url:

import { google } from 'googleapis';

const buildAuth = function () {
  return new google.auth.OAuth2(
    '0000000000000-xxxxxxxx.apps.googleusercontent.com', // clientId
    'XXXXXXXXXXXXXXXXXXX', // clientSecret
    'http://localhost:7777/google/callback', // redirect
  );
};

Step 4. Add the Login Route

In that same file, we’ll add a route for starting the login process. If a user wishes to login with Google, send them to /google/login and this route will redirect them to Google.

app.get('/google/login', async (req, res) => {
  const auth = buildAuth();
  const url = auth.generateAuthUrl({
    access_type: 'offline',
    prompt: 'consent',
    scope: [
      'https://www.googleapis.com/auth/userinfo.email',
      'profile',
    ]
  });
  res.redirect(url);
});

So we build our auth client then generate an authentication url. You can add more scopes but you’ll need these two if you want their email address. Then redirect the user to that url. They will now see the Google login page.

Step 5. Handle Google’s Response

Once they login, google will send them back to the URL you provided twice. You entered it when you setup credentials and you entered it when you built the auth client in your code. Remember – those have to match exactly!

So the user logs in and google sends them back to your url but adds a query string parameter called “code”:

/google/callback?code=3/yQVdAynpi2RQ_z_vsvS6XrskZukZ8_eZ5mm2-YcgPihTzgwo96Sj37AA2FdGY3IUlic5IPn9TEqWmU_eSrAxaSY

You’ll take that code & exchange it for a token. Then you can use the token to load profile information that you listed in your scope. Here we fetch the emailAddresses property:

app.get('/google/callback', async (req, res) => {
  // get & set tokens
  const { code } = req.query;
  const auth = buildAuth();
  const { tokens } = await auth.getToken(code);
  auth.setCredentials(tokens);

  // fetch the user's email
  const peopleApi = google.people({version: 'v1', auth}).people;
  const me = await peopleApi.get({
    resourceName: 'people/me',
    personFields: 'emailAddresses',
  });
  const address = me.data.emailAddresses.find(e => e.metadata.primary);
  const email = address && address.value;

  // TODO: login with email

  res.redirect('/');
});

You’ll need to implement the TODO portion – use the email address to find or create a user, then sign them in.

And that’s it! My entire google authentication implementation is 50 lines of code. Amazing!

See the complete google-routes.js source code at: https://gist.github.com/bendytree/e57868232eaf35271f0c83c9a57b1c2c

Leave a Reply

Your email address will not be published. Required fields are marked *