Create an Angular 7 + Google Authenticator + Node JS Web App with Two-Factor Authentication

Written by narendrakamath | Published 2019/04/15
Tech Story Tags: javascript | tutorial | authentication | nodejs | angular

TLDRvia the TL;DR App

“Turn on all security features like two-factor authentication. People who do that generally don’t get hacked. Don’t care? You will when you get hacked. Do the same for your email and other social services, too.” — Robert Scoble

“Extra layer of security” — who doesn’t need it? Is your website having a provision to enable Two-Factor authentication (TFA) for your users? Yes, you would definitely need your user-base to be more secure than just having a password based authentication.

In this tutorial we’ll learn how to easily enable and integrate the 2-Factor Authentication in an Angular-7 app using Node JS as the back-end technology along with Google Authenticator, that provides Time based — One Time Password(TOTP). By the end of this post, you will be able to create an application that has a simple login and registration feature along with the 2-Factor Authentication.

GitHub repository to be followed: angular-node-mfauth (https://github.com/Narendra-Kamath/angular-node-mfauth)

Application Demo Video

<a href="https://medium.com/media/138a83424fb4aa6cd8e427c828200cd7/href">https://medium.com/media/138a83424fb4aa6cd8e427c828200cd7/href</a>

Prerequisites

  1. Node JS (LTS) — [Download] (using v10.15.3 LTS in the tutorial)
  2. Google Authenticator — [Download: Android] [Download: iOS]

After having the above mentioned tools being installed, the next step would be to create the API services for the application.

Step 1: Server-side Application

For creating the API services, we would be using the minimal and flexible web framework for Node.js called as Express.js. Let us now create a dedicated directory ‘back-end’ for our server-side app and navigate into that folder in the terminal/ command prompt and install the required project dependencies.

> mkdir back-end
> cd back-end
> npm init -y
> npm install --save express body-parser cors qrcode speakeasy

Now, we have created a directory ‘back-end’ and initialized it as a Node.js project by installing the following dependencies:

  1. express — This is a minimal and flexible web framework for creating API services.
  2. body-parser — In order to parse the HTTP method’s body data, this package is being used.
  3. cors — This package is used in order to enable the client side web application to communicate with the API services and to avoid the cross-origin issue.
  4. qrcode — In this application we would be generating the QR-code as a base64 image data, and thus we require qrcode package.
  5. speakeasy — This is the package that enables our application to provide with the secret key and the T-OTP algorithm that the Google Authenticator uses and is also useful for the verification of the Auth code being provided.

We will now create a few API services, with app.js as the main file of execution. For the simplicity of learning process, separation of concerns is followed for the scaffolding of the application.

Folder structure for back-end

The API services will expose the features of login, registration and TFA with the following routes:

  1. Login service: The login service for the application would include the basic functionalities for a login using the username, password and Auth Code if TFA is enabled or else just with the username and password.

<a href="https://medium.com/media/43216c0e3fd70f80294467906a4e50bd/href">https://medium.com/media/43216c0e3fd70f80294467906a4e50bd/href</a>

In this tutorial we wouldn’t be using a Database to store the user object and hence we would be using a common and shared user object on the server side.

<a href="https://medium.com/media/4252f7e0b68885431e923b98063f0958/href">https://medium.com/media/4252f7e0b68885431e923b98063f0958/href</a>

2. Registration service: The registration of a user in the application would be just to add the username and password to the userObject as well as to reset the already existing userObject information. Since the login and registration modules are made just for the demonstration purpose, the application will support only a single user login and registration.

<a href="https://medium.com/media/be06514234aeb2d4bcc54909180e9ecd/href">https://medium.com/media/be06514234aeb2d4bcc54909180e9ecd/href</a>

3. TFA service: This service is to provide a feature for the setup of the two factor authentication along with the verification of the T-OTP code generated by Google Authenticator. The service would include the functionalities to GET the existing TFA configuration as well as to enable or disable the TFA for a userObject.

<a href="https://medium.com/media/e696b50a8159e0caefa31021db7caab9/href">https://medium.com/media/e696b50a8159e0caefa31021db7caab9/href</a>

The above mentioned routes are exported for a common integration and single entry file in the root directory ‘app.js.’ This would start the express generated HTTP server on the localhost with port number 3000.

<a href="https://medium.com/media/cc09e205798d56f36e661da3dd1381b2/href">https://medium.com/media/cc09e205798d56f36e661da3dd1381b2/href</a>

Thus we have setup the server side code for our web application. The server script could be started and let it Rest In its Place ;)

Now the next step would be to create a simple Angular 7 application to consume these created services.

Step 2: Angular 7 application

For creating an Angular 7 application, we should first install Angular globally. After installing angular, we’ll create an app by the name ‘front-end’ and we’ll also install the local dependency of ‘bootstrap’ (link the bootstrap.min.css in styles.css) by navigating to front-end directory.

> npm install -g @angular/cli
> ng new front-end
> cd front-end
> npm install --save bootstrap
> ng serve

After successfully creating the angular app and launching the app server, we’ll generate a few components, guards and services required for the application.

For the purpose of demonstration we would be creating a LoginService and two guards — ‘Auth Guard’ and ‘Login state management Guard.’

> ng g s services/login-service/login-service --spec=false
> ng g g guards/AuthGuard
> ng g g guards/Login

The guards generated here are the CanActivate guards. The login-service would include the HTTP calls to the services created at back-end.

<a href="https://medium.com/media/3859a27ac903b1803199b61ddf0b23ae/href">https://medium.com/media/3859a27ac903b1803199b61ddf0b23ae/href</a>

The AuthGuard would restrict the user to navigate to the Home page without login.

<a href="https://medium.com/media/08a5da3ebdb3ee9fe05c42ff5f375a83/href">https://medium.com/media/08a5da3ebdb3ee9fe05c42ff5f375a83/href</a>

The login-guard would not allow the user to navigate to login or registration page if the user is already logged-in.

<a href="https://medium.com/media/e7ea9fdaf13c0311e4a90e02fa46e929/href">https://medium.com/media/e7ea9fdaf13c0311e4a90e02fa46e929/href</a>

Since we have completed with the backbone for our application by creating the services and guards, we’d now create a few major components and also configure the routing for the application.

> ng g c components/header --spec=false
> ng g c components/home --spec=false
> ng g c components/login --spec=false
> ng g c components/register --spec=false

After creating the necessary components for the app, we’ll now configure the routing for the app, by linking the respective guards for activating the routes.

<a href="https://medium.com/media/124fb605fd858edd14109016b273da0d/href">https://medium.com/media/124fb605fd858edd14109016b273da0d/href</a>

Let’s now have some code done on the components created, before which we have to remove the default code in app.component.html, and we’ll just mention the common header component and the router-outlet.

<a href="https://medium.com/media/dcbaf8c95868871f80a79684a6841622/href">https://medium.com/media/dcbaf8c95868871f80a79684a6841622/href</a>

  1. Header Component: This is a common component for the other components, that includes a navigation bar for the application. The visibility of the links in the header are controlled by the getAuthStatus() of LoginService.

<a href="https://medium.com/media/860e16260fdad1a3367a59244732bcf5/href">https://medium.com/media/860e16260fdad1a3367a59244732bcf5/href</a>

In the background of this HTML, we would require the *.ts file as well, for the header component.

<a href="https://medium.com/media/fe3517d7cd513cb91a8b23e95682c3ba/href">https://medium.com/media/fe3517d7cd513cb91a8b23e95682c3ba/href</a>

2. Login Component: This is a simple component to accept the username, password and the AuthCode (if TFA is enabled) from the user and to verify it with the back-end services. If the user information is valid, then the user will be navigated to the HomeComponent.

<a href="https://medium.com/media/15b8ec18afeb6af06a7e382c531ee92a/href">https://medium.com/media/15b8ec18afeb6af06a7e382c531ee92a/href</a>

We would also be verifying the status received from the back-end to display appropriate messages to the user.

<a href="https://medium.com/media/267a7a98a38f1c5408a8ea7fe73eadcc/href">https://medium.com/media/267a7a98a38f1c5408a8ea7fe73eadcc/href</a>

3. Registration Component: As stated earlier in this post, we would be able to register a single user in the whole application and we would require the user to enter any username and password (certainly the one that you would remember :P ) for the registration purpose.

<a href="https://medium.com/media/b132bd3fa27d41a1f4f2cbbeaf40dc39/href">https://medium.com/media/b132bd3fa27d41a1f4f2cbbeaf40dc39/href</a>

In case you forget your username or the password provided for the application or in case if you miss the TFA secret key in your device, then simply provide a new username and password in the registration page (basically you would be resetting the userObject :P).

<a href="https://medium.com/media/4c2a3bdf827a4d3774f8d4f2639b05a0/href">https://medium.com/media/4c2a3bdf827a4d3774f8d4f2639b05a0/href</a>

Login and Registration page

Once the user is registered and logged in with the username and password, the user will be provided with an option to enable or disable the Two-Factor Authentication in the HomeComponent.

4. Home Component: In this component, we would be allowing user to setup and verify the TFA. As soon as you land on this page, there will be an option to setup the TFA, where the QR-Code, which is to be scanned in the Google Authenticator app. As soon as you scan, the T-OTP (TFA element) linked with the userObject will be included in the Google Authenticator app. The AuthCode will be displayed on time basis in the app and the same code should be entered in order to verify and enable TFA for the userObject.

<a href="https://medium.com/media/27763332fe9df92644e44fba0aaf883d/href">https://medium.com/media/27763332fe9df92644e44fba0aaf883d/href</a>

If the user has enabled TFA, then the current settings with the QR-Code and Secret Key will be displayed, along with an option to disable the TFA linked with userObject.

<a href="https://medium.com/media/6d93e7d0ca6fe194064731bdc3a5cba6/href">https://medium.com/media/6d93e7d0ca6fe194064731bdc3a5cba6/href</a>

Setup TFA and Current Settings of TFA

Hurray!! If you have reached till this length of the post, then you have successfully learnt of how to easily integrate the Two-Factor Authentication in your Angular 7 application. For any debugging process, you may look at the console of either the front-end application or the back-end application. Hope it was easy to integrate Two-Factor Authentication with your Angular 7 app… Cheers!!

Kindly share your views in the responses section :) Thank you!


Published by HackerNoon on 2019/04/15