M.E.R.N stack application using Passport for authentication.

Written by balasubramanim | Published 2018/06/12
Tech Story Tags: javascript | web-development | react | authentication | passport-for-auth

TLDRvia the TL;DR App

In this tutorial, we will be integrating Google sign-in for registration or login purpose in our React application using Passport authentication mechanism in Node.js server.

Photo by Steve Halama on Unsplash

In today’s world, the user prefers single sign-in option using any of their social accounts in every site they visit rather than giving their credentials again to another person.

So, it is necessary now to integrate single sign-in to make thing easier, and allowing only verified users in your application which mutually benefits both the user and the app owners.

Straightaway, let’s jump into development.

Create React App with Google Sign-in button

Step 1: Let’s create a basic react application using create-react-app

$ npx create-react-app my-app$ cd my-app$ npm start

Step 2: In App.js in the root directory, add the following HTML code to create a button after the P tag in the render() function.

<a href="/auth/google" class="button"><div><span class="svgIcon t-popup-svg"><svgclass="svgIcon-use"width="25"height="37"viewBox="0 0 25 25"><g fill="none" fill-rule="evenodd"><pathd="M20.66 12.693c0-.603-.054-1.182-.155-1.738H12.5v3.287h4.575a3.91 3.91 0 0 1-1.697 2.566v2.133h2.747c1.608-1.48 2.535-3.65 2.535-6.24z"fill="#4285F4"/><pathd="M12.5 21c2.295 0 4.22-.76 5.625-2.06l-2.747-2.132c-.76.51-1.734.81-2.878.81-2.214 0-4.088-1.494-4.756-3.503h-2.84v2.202A8.498 8.498 0 0 0 12.5 21z"fill="#34A853"/><pathd="M7.744 14.115c-.17-.51-.267-1.055-.267-1.615s.097-1.105.267-1.615V8.683h-2.84A8.488 8.488 0 0 0 4 12.5c0 1.372.328 2.67.904 3.817l2.84-2.202z"fill="#FBBC05"/><pathd="M12.5 7.38c1.248 0 2.368.43 3.25 1.272l2.437-2.438C16.715 4.842 14.79 4 12.5 4a8.497 8.497 0 0 0-7.596 4.683l2.84 2.202c.668-2.01 2.542-3.504 4.756-3.504z"fill="#EA4335"/></g></svg></span><span class="button-label">Sign in with Google</span></div></a>

Step 3: Add the following CSS to dress up your button in the index.css file in the root directory.

a {-webkit-tap-highlight-color: transparent;text-decoration: none;}

.button {display: inline-block;max-width: 300px;margin-top: 50px;border: 0;padding: 0 18px;text-align: left;width: 100%;height: 37px;border-radius: 4px;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;-moz-font-feature-settings: "liga" on;color: rgba(0, 0, 0, 0.84) !important;fill: rgba(0, 0, 0, 0.84) !important;box-shadow: 0 1px 7px rgba(0, 0, 0, 0.05);font: inherit;outline: none;}

.button .svgIcon {vertical-align: middle;fill: rgba(0, 0, 0, 0.54);padding-right: 4px;height: 37px;display: inline-block;}

That’s it. You have created a button with the link to navigate to Google authentication page on click (Check href attribute in <a> tag).

/auth/google

React app with Google sign-in button.

Note: Now, our client is running in the port 3000.

We will be handling Routes later in this tutorial. So I request you to install the following module in your application.

$ npm i --save react-router-dom

And replace the code in the index.js file with the below code.

import React from "react";import ReactDOM from "react-dom";import "./index.css";import App from "./App";import registerServiceWorker from "./registerServiceWorker";import { Route, Switch } from "react-router-dom";import { BrowserRouter } from "react-router-dom";

ReactDOM.render(<BrowserRouter><Switch><Route path="/" component={App} /></Switch></BrowserRouter>,document.getElementById("root"));registerServiceWorker();

We are just importing Route, Switch and BrowserRouter from “react-router-dom” and replacing some code in render function to support routes in our application.

We will access query param from URL and replace it later in this tutorial. You could able to access router properties (props in react) only when you have configured your App to support router. To know more about the router and its configuration, go through this link.

Set up Node.js server and configure Passport

I hope now you see the below screen with the button. Let’s create a Node.js server now and implement the server side logic.

I am going to create a separate Node.js server and run in another port since maintaining server and client in different code base will be easier to maintain and doesn’t depend on each other as per my knowledge.

Step 4: Create Node.js server and install Passport modules.

If you aren’t aware of creating a Node.js server, you don’t need to worry. I have created a tutorial on creating a Node.js server from scratch to production. Kindly go through the below link and follow the topic called Create a sample Node.js server and create one before proceeding if you don’t have a server.

Deploy your Node.js app in production and use BitBucket to automate your deployment._In this tutorial, we will be creating a sample Node.js server, pushing it to BitBucket and using PM2, we will automate…_medium.com

So we have a server now but we don’t have passport module in our server. Navigate to your server and install passport and passport-google-oauth

$ cd my-server/$ npm i passport --save$ npm i passport-google-oauth --save

We have installed the required modules. Let’s make use of it by adding the below two lines in the app.js file.

var passport = require(“passport”); // at header

app.use(passport.initialize()); // after line no.20 (express.static)require("./config/passport");

Change default server port from 3000 to 4500 to avoid conflicts between server and client. Go to bin/www file and change 3000 to 4500 and start your application by issuing the following command.

$ npm start

Note: Now, our server is running on the port 4500.

Step 5: Let’s create a passport.js file which handles our passport authentication mechanisms.

Create a folder called config in your root directory and inside create a file called passport.js with the following content in it.

var passport = require("passport");var GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;

passport.serializeUser(function(user, done) {done(null, user);});

passport.deserializeUser(function(user, done) {done(null, user);});

passport.use(new GoogleStrategy({clientID: "GOOGLE_CLIENT_ID",clientSecret: "GOOGLE_CLIENT_SECRET",callbackURL: "http://localhost:4500/auth/google/callback"},function(accessToken, refreshToken, profile, done) {var userData = {email: profile.emails[0].value,name: profile.displayName,token: accessToken};done(null, userData);}));

As you see, we need GOOGLE_CLIENT_ID & GOOGLE_CLIENT_SECRET for your application. You can get one at https://console.developers.google.com/

Step 6: Configure your app in the Google Developers dashboard

Navigate to Google developers console and create your application.

Credentials page in Google Developers Console.

In the above page, click Create credentials and select OAuth client ID.

In the next screen, select Application type as a Web application and name your application.

In the Restrictions part, you need to provide your app URL and redirect URL to prevent others misusing your application.

Provide your app URL as follows in the Authorised JavaScript origins. You can add multiple entries here.

http://localhost:4500

Since our server is running in the port 4500. (Allowing server to authenticate)

Provide your redirect URI as follows in the Authorised redirect URIs.

http://localhost:4500/auth/google/callback

Since we need to redirect back to our server after Google authentication gets completed. (We have also mentioned this URL in our passport.js file, look at it)

Save and get your GOOGLE_CLIENT_ID & GOOGLE_CLIENT_SECRET key and paste it in your passport.js file.

Finally, click Library which is above Credentials and search for Google+ API. Select and enable to get a user’s Google+ profile.

Step 7: Create routes to handle Google Authentication

Let’s create an API call called /auth/google which our client calls after clicking the Sing up with Google button.

Go to index.js in routes folder and add the following line at the header.

var passport = require(“passport”);

and below lines after the default get request.

/* GET Google Authentication API. */router.get("/auth/google",passport.authenticate("google", { scope: ["profile", "email"] }));

router.get("/auth/google/callback",passport.authenticate("google", { failureRedirect: "/", session: false }),function(req, res) {var token = req.user.token;res.redirect("http://localhost:3000?token=" + token);});

That’s it. You have configured your server.

I will explain what is happening in the above lines.

First route /auth/google which gets the request from the client, authenticate with Google using a passport. We are providing “profile” & “email” in scope array to get user’s profile and email address. You can check the list of available scopes at Google OAuth 2.0 Scopes.

A Second route, /auth/google/callback which invokes after the user completes the Google Authentication. When you check at the passport.js file, we are creating an object with required fields sending it back to the callback function.

In routes/index.js file, in callback function in /auth/google/callback route, we access this object through req.user.

How req.user holds that value?

Because we use serializeUser and deserializeUser function in a passport.js file which holds the response received from Google in user value and so we can access this object through the same.

Finally, we are redirecting back to our client app which is running in the port 3000 with a token in the query param.

Step 8: Receive token and authenticate the user

Now let’s receive this token and authenticate the user.

Back to our client app. Install the following module to parse query string in our react app using the following command from your root directory.

npm i query-string --save

import this module in our App.js file at the header.

import queryString from "query-string";

Now, let’s create a component lifecycle method called componentWillMount.

This method will get invoked when our app starts. Check out React Life Cycle Components for more info.

Insert the following code in App.js before render method.

componentWillMount() {var query = queryString.parse(this.props.location.search);if (query.token) {window.localStorage.setItem("jwt", query.token);this.props.history.push("/");}}render(){...}

This method will get the query param token from the URL during initialization and set it in local storage.

Finally, replace the token in the URL.

Now you have a token which represents the visitor is an authenticated user to use your app. Use this token in every request to your API server from now.

Hope this will be useful to implement basic authentication system in your MERN stack app.

Client App: https://github.com/BalasubramaniM/react-nodejs-passport-app

Server App: https://github.com/BalasubramaniM/react-nodejs-passport-server

Thank you.


Published by HackerNoon on 2018/06/12