Implementing Facebook, Google and Email Authentication in NodeJS

Zoran Šaško
The Startup
Published in
6 min readAug 16, 2020

Every web application that stores user data need to have login and registration functionality. Besides of email login functionality, we can add login with different social network providers like Google, Facebook etc.

In this article we’ll explore how we can login with email, Google and Facebook. In the article we’ll also cover storing user data in MySQL database and user input validation.

At the end of this article you’ll find code sample, so if you have missed some steps, you can see the complete code sample.

Firstly, we need to put some dependencies in ‘package.json’:

In order to install all the required dependencies, we need to run the following command:

npm install

If you’ll encounter in some problem with parsing ‘package.json’ file, please execute the following commands:

npm cache clean — force
npm install

After installing all required dependencies, we can import them in ‘App.js’. We are going to initialize MySQL connection, initialize session and initialize other objects required for our web application. We are going to use ‘EJS’ templating engine and web pages will be stored in ‘views’ folder. Data model files will be stored in ‘models’ folder and configuration files will be stored in ‘config’ folder.

In ‘.env’ file we need to specify some general variables and the MySQL connection variables:

We are going to use Sequelize ORM for fetching and storing data in MySQL database. Sequelize has it’s own CLI so we will use this tool to generate data model for us.

Firstly we need to initialize Sequelize by executing the following command:

npx sequelize init

and after that, we are going to generate our ‘User’ data model:

npx sequelize-cli model:generate --name User --attributes name:string,email:string,social_user_id:string,password:string,registration_type:enum:'{email,google,facebook}'

In ‘models’ folder you can see newly generated ‘User’ model and in migrations you can see migration generated by ‘User’ model. You can see that we have also specified data types for different attributes of ‘User’ class, in ‘sequelize-cli’ command above.

Before we can execute the command that will create appropriate model in our MySQL database, we need to edit MySQL connection settings. We are going to use custom Sequelize configuration that will take connection data from ‘.env’ variable (instead of using connection data from ‘config.json’ file). So in order to do that, we are going to create ‘.sequelizerc’ file with path of database configuration file (file ‘config/config.js’):

And in ‘config/config.js’ we are going to set MySQL connection variables to be loaded from ‘.env’ file:

In ‘models/index.js’ we need to modify ‘config’ constant in order to load configuration from ‘.js’ file, instead of ‘.json’ file:

const config = require(__dirname + ‘/../config/config’)[env];

Now we are ready to make an migration, by invoking the following command

npx sequelize db:migrate

After successfully invoked migration, we can proceed with designing layout.

First layout file that we are going to make is home page (‘views/index.ejs’). In home page we are going to show appropriate messages in case if use is not authorized and if it’s authorized:

and for main menu we are going to use layout that will be reusable (‘menu.ejs’ file), so we need to put it in ‘partials’ folder:

Login via email

Configuration data for login via email, Facebook or Google is set in ‘config/passport.js’ file. In order to add configuration for email login, we need to add ‘LocalStrategy’.

In ‘LocalStrategy’ we are checking if user with the requested email exist. If it doesn’t exist we are sending appropriate callback notification. If it does exist, we are checking if our password is the same as encrypted password from user stored in database, by using ‘bcrypt.compare’ method.

Layout for the login, will also have very basic layout:

and here we’ll going to use some other reusable component, for displaying error messages (‘flash_messages.ejs’ file):

Now we need to link our newly created layout files with appropriate routes, so in ‘routes’ folder we’ll add ‘index.js’ route file:

In ‘App.js’ we are going to load this route:

const { getHomePage } = require(‘./routes/index’);

and assign it to appropriate request method:

app.get(‘/’, getHomePage);

So, now when we open our main application page, we’ll see home page.

Let us make an login route:

And we need to assign those routes in ‘App.js’ file:

const { handleLogout, postLogin, getLogin } = require(‘./routes/login’);

To appropriate request methods:

app.post(‘/login’, postLogin);
app.get(‘/login’, getLogin);
app.get(‘/logout’, handleLogout);

And now we can test the email login.

For email registration (‘register.ejs’ file), we are going to use the following form:

In order to display registration form, we are going to create methods that will handle registration route methods:

In ‘submitRegister’ method we can see that we are firstly validating user input. We are checking if user has entered the fields with right length and if email is not already used. After that, we are creating new user and redirecting it to default route (‘/’).

Note that we’ll need use registration form only for email registration, since registration via social networks will use Object data that is provided with appropriate social network library.

Now we need to add registration routes in App.js:

const { getRegister, submitRegister } = require(‘./routes/register’);app.get(‘/register’, getRegister);
app.post(‘/register’, submitRegister);

Now we can check how registration via email works :)

Login via Facebook

Before we can implement login via Facebook in out app, we need to create API keys in Facebook app following the steps:

  1. In Developers Facebook page (https://developers.facebook.com/apps/) create new application and add ‘Facebook Login’ as a product.
  2. Choose ‘Web’ integration.
  3. For ‘Site URL’ we can put ‘http://localhost’.

For local development, we dont’t need to specify redirect url-s, but we need to put valid url if we are deploying app to production server.

Make sure that in ‘.env’ file, you have added appropriate facebook keys, like:

FACEBOOK_APP_ID=your_fb_app_id
FACEBOOK_APP_SECRET=your_fb_app_secret
FACEBOOK_APP_CALLBACK_URL=http://localhost:5003/auth/facebook/callback

Now we need to add appropriate strategy in ‘config/passport.js’, so passport library will be able to handle facebook login callbacks.

On the top of ‘passport.js’ we’ll import ‘FacebookStrategy’ object:

const FacebookStrategy = require(“passport-facebook”).Strategy;

and we’ll specify other configuration options required for Facebook authorization:

In asynchronous function in ‘FacebookStrategy’, we are creating new user if it doesn’t exist and returning already existing user to callback ‘cb’.

In order to display facebook login page, we need to add two methods for handling facebook login routes:

and for above specified methods, we need to assign appropriate routes:

const { getFacebookLogin, handleFacebookLogin } = require('./routes/facebook_login');app.get(‘/auth/facebook’, getFacebookLogin);
app.get(‘/auth/facebook/callback’, handleFacebookLogin);

In the similar way, we are going to implement login via Google.

Login via Google

In order to make Login via Google possible, we need to create appropriate project and API keys.

The steps to get Google API Keys:

  1. In Google Api Console (https://console.developers.google.com/) create new project.
  2. In ‘Credentials’ page and create new ‘OAuth Client ID’. If you need to create content for consent screen, in ‘Oauth Consent screen’ choose ‘External’ as ‘User Type’ and get back to ‘Creadentials’ page to start creating ‘OAuth Client ID’ again.
  3. In ‘Authorized Redirect URIs’ field add calback url:
    http://localhost:5000/auth/google/callback

Make sure that in ‘.env’ file, you have added appropriate google keys, like:

GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_APP_CALLBACK_URL=http://localhost:5000/auth/google/callback

Firstly we need to import Google Strategy in passport.js:

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

And we need to add ‘GoogleStrategy’, to ‘passport’ object:

Similarly like in ‘FacebookProvider’, in ‘GoogleProvider’ asynchronous function we are going to return existing user or insert new user, if user is not already existing.

Google login methods we are specifying in ‘google_login.js’ route file:

and they need to be assigned to appropriate routes in ‘App.js’:

const { getGoogleLogin, handleGoogleLogin } = require(‘./routes/google_login’);app.get(‘/auth/google’, getGoogleLogin);
app.get(‘/auth/google/callback’, handleGoogleLogin);

Congratulations, you have successfully created application with multiple authorization providers!

Source code of sample application built in this article:

--

--