Facebook Authentication for NodeJS

1 min read

For some reason, OAuth always seems overly complicated. Documentation stinks and errors are vague. Abstractions like Passport.js add a mountain of complication while barely reducing friction. Does it have to be this hard? Actually, no.

Facebook authentication for NodeJS is actually pretty easy.

Step 1. Get Credentials

First you need credentials. Buckle up because this is really the only challenging part.

Go find or register a new Facebook app. Then enable the Facebook Login product. It will try to take you through a Quickstart, but skip that – click the Settings button instead and you’ll see this screen:

You don’t need to change anything except “Valid OAuth Redirect URIs”. This is the URL that facebook will redirect your user to after logging in. Facebook will automatically allow localhost urls for testing, so enter your production url. I made up the /facebook/callback part as you’ll see below. Facebook will also append a code parameter in the query string.

Now click Settings > Basic on the left. You should now have your App ID, App Secret, and Redirect URL.

Step 2. Send Them To The Login Page

We’ll use the query-string package on npm to create the login url.

npm install --save query-string axios

Now create an express route. The user goes to /facebook/login and gets redirected to the login page:

import app from ???;
import * as qs from 'query-string';

const settings = {
  appId: '*****************',
  appSecret: '************************',
  redirectUrl: 'http://localhost:7777/facebook/callback',
};

app.get('/facebook/login', async (req, res) => {
  const params = qs.stringify({
    client_id: settings.appId,
    redirect_uri: settings.redirectUrl,
    scope: ['email'].join(','),
    response_type: 'code',
    auth_type: 'rerequest',
    display: 'popup',
  });

  const url = `https://www.facebook.com/v4.0/dialog/oauth?${params}`;
  res.redirect(url);
});

Pretty simple. See all available query string options here. We’re just loading email but see all scopes here. Consider using the dotenv package for a better way to store sensitive settings.

Step 3. Setup The Callback

So you sent the user to the login page, now Facebook sends them back with a code parameter. You need to use that code to find the user’s email:

app.get('/facebook/callback', async (req, res) => {
  // Get the login code
  const { code } = req.query;

  // Fetch the access token
  const tokenResponse = await axios({
    url: 'https://graph.facebook.com/v4.0/oauth/access_token',
    method: 'get',
    params: {
      client_id: settings.appId,
      client_secret: settings.appSecret,
      redirect_uri: settings.redirectUrl,
      code,
    },
  });
  const { access_token } = tokenResponse.data;

  // Fetch the email
  const meResponse = await axios({
    url: 'https://graph.facebook.com/me',
    method: 'get',
    params: {
      fields: ['email'].join(','), // matches scope
      access_token,
    },
  });
  const { email } = meResponse.data;

  // TODO: login with email

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

So we use the code to get the token. Then use the token to get the email. 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 facebook authentication implementation is 50 lines of code and very readable. Amazing!

See the complete facebook-auth-routes.js source code at: https://gist.github.com/bendytree/67ec68628f808b88aa3136bb1e2e7f97

Leave a Reply

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