PROGRAMS

Combined Login and Registration Application in AngularJS

Authentication is the process of identifying whether a client or a user is someone who he/she claimed to be. Generally, the authentication process enables certain extra functionality to the user. Web applications make use of HTTP protocols for transactions between the server and the client. This HTTP protocol supports authentication as a means of providing access to the server’s secured resources.

The most common authentication method used in HTTP is “Basic” authentication. This mechanism is the process of passing user credentials in a form of Base64 encoded string in authorization header of HTTP request. The credentials are then verified and the response is being sent to the client. If credentials are wrong then the unauthorized status response is sent to the client.

In this application, we will demonstrate a combined Login and Registration Application in AngularJSThis example makes use of HTML5 web storage feature i.e. we will use local storage for storing the user details locally in user’s browser/computer, permanently. It is similar to cookies but the data stored on local storage is not sent to the web server like cookies where data sent to the server in every request. Unlike cookies, it can store any amount of data. Hence this approach is faster and secure. It uses “localStorage” object to store the data. Form validation using attributes and ngMessages is already explained covered in the previous articles.

Suggested articles:

Following are the Requirement details for this application are as follows. Combined Login and Registration Application

  1. Login page
    • Username
    • Password
    • Login and Register buttons
  1. Registration page
    • First Name
    • Last Name
    • Username
    • Password
    • Register and Cancel buttons
  2. Home page
    • It should display the user’s full name with a welcome message.
    • It should display all the registered users in an appropriate format.
    • Logout and View-Users buttons
  1. Functionality
    • When the application is run, the Login page will appear.
    • When the user enters the details and tries to log in, his credentials will be   So before login user needs to register themselves using Register button on the login page. Once he is done with registration he can log in with these details.
    • If the user successfully logs-in, he will be taken to the home page.

 

Following are the filenames used in this application.

The index.html gets loaded initially. In the index.html, we have registered angular scripts, bootstrap styling scripts, and all the controller javascript files. Also, we have an ng-view for loading each view page according to routing action.

<!--index.html-->
<!DOCTYPE html>
<html ng-app="app">
<head>
    <meta charset="utf-8" />
    <title>AngularJS Basic HTTP Authentication Example</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="jumbotron">
        <div class="container">
          <div class="header">AngularJS Basic HTTP Authentication Example</div>
            <div class="col-sm-8 col-sm-offset-2">
                <div ng-view></div>
            </div>
        </div>
    </div>
    
    <script src="//code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="//code.angularjs.org/1.6.0/angular.min.js"></script>
    <script src="//code.angularjs.org/1.6.0/angular-route.min.js"></script>
    <script src="//code.angularjs.org/1.6.0/angular-cookies.min.js"></script>
    
    <script src="app.js"></script>
    <script src="homeController.js"></script>
    <script src="loginController.js"></script>
    <script src="registerController.js"></script>
    
    <script src="userService.svc.js"></script>
    <script src="authenticationService.svc.js"></script>
</body>
</html>

 

Now, we will create our application module. In the below code, app.js we have created an app module and invoked ngRoute for routing mechanism and ngCookies for storing user credentials in cookies. The config() function is used for configuring routes using $routeProvider. Run() function is used for the initial logic whenever the application is run where we are just clearing the console logs.

//app.js
(
function () {
    'use strict';

    angular
        .module('app', ['ngRoute', 'ngCookies'])
        .config(config)
        .run(run);

    config.$inject = ['$routeProvider', '$locationProvider'];
    function config($routeProvider, $locationProvider) {
        $routeProvider
        .when('/', {
                controller: 'LoginController',
                templateUrl: 'login.html',
                controllerAs: 'vm'
            })

            .when('/home', {
                controller: 'HomeController',
                templateUrl: 'home.html',
                controllerAs: 'vm',
            })            
            .when('/register', {
                controller: 'RegisterController',
                templateUrl: 'register.html',
                controllerAs: 'vm'
            })
            .otherwise({ redirectTo: '/login' });
    }    
    run.$inject = ['$rootScope'];
    
    function run(){
      console.clear();
    }
})();

 

If the user does not have an existing account to log-in, he/she must create an account by registering to get the credentials. The following code explains the register.html.

//register.html
<div class="col-md-6 col-md-offset-3">
    <h4 style="text-align:center;color:blue">Register</h4>
    <form name="form" ng-submit="vm.register()" role="form">
        <div class="form-group" ng-class="{ 'has-error': form.firstName.$dirty && form.firstName.$error.required }">
            <label for="username">First name</label>
            <input type="text" name="firstName" id="firstName" class="form-control" ng-model="vm.user.firstName" required />
            <span ng-show="form.firstName.$dirty && form.firstName.$error.required" class="help-block">First name is required</span>
        </div>
        <div class="form-group" ng-class="{ 'has-error': form.lastName.$dirty && form.lastName.$error.required }">
            <label for="username">Last name</label>
            <input type="text" name="lastName" id="Text1" class="form-control" ng-model="vm.user.lastName" required />
            <span ng-show="form.lastName.$dirty && form.lastName.$error.required" class="help-block">Last name is required</span>
        </div>
        <div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
            <label for="username">Username</label>
            <input type="text" name="username" id="username" class="form-control" ng-model="vm.user.username" required />
            <span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
        </div>
        <div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
            <label for="password">Password</label>
            <input type="password" name="password" id="password" class="form-control" ng-model="vm.user.password" required />
            <span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
        </div>
        <div class="form-actions">
            <button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Register</button>
            <img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgA" /> <!-- truncated line -->
            <a href="#!/" class="btn btn-link">Cancel</a>
        </div>
    </form>
</div>

From the register.html, the register() function gets called on Register button event click. In this method, we are taking user inputs and passing them to create() function in UserSrvice. It will respond back with either success or failure and the message is shown to the user in UI.

//registerController.js
(function () {
    'use strict';

    angular
        .module('app')
        .controller('RegisterController', RegisterController);

    RegisterController.$inject = ['UserService', '$location'];
    function RegisterController(UserService, $location) {
        var vm = this;

        vm.dataLoading = false;
        vm.register = register;

        function register() {
            vm.dataLoading = true;
            UserService.create(vm.user)
                .then(function (response) {
                    if (response.success) {
                        alert('Registration successful');
                        $location.path('/');
                    } else {
                        alert(response.message);
                        vm.dataLoading = false;
                    }
            });
        }
    }
})();

 

Next, we will build the login.html. The login form basically contains a placeholder to key-in username and password.

<!--login.html-->
<div class="col-md-6 col-md-offset-3">
    <h4 style="text-align:center;color:blue">Login</h4>
    <form name="form" ng-submit="vm.login()" role="form">
        <div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
            <label for="username">Username</label>
            <input type="text" name="username" id="username" class="form-control" ng-model="vm.username" required />
            <span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
        </div>
        <div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
            <label for="password">Password</label>
            <input type="password" name="password" id="password" class="form-control" ng-model="vm.password" required />
            <span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
        </div>
        <div class="form-actions" layout="row">
            <button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Login</button>
            <img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///" /> <!-- truncated line -->
            <span style="float:right">Not a member?<a href="#!/register" class="btn btn-link">Register</a></span>
        </div>
    </form>
</div>

 

When a user submits his information from the login form, the information is passed to the controller javascript, loginController.js file. In this code, we are adding a reference for the AuthenticationService to authenticate the user credentials when login() function is invoked and the $location is used for navigating between pages after the user successfully logs-in into the application. If a user fails to log in a popup with is failure message is displayed. The following code explains loginController.js.

//loginController.js
(function () {
    'use strict';
    angular
        .module('app')
        .controller('LoginController', LoginController);

    LoginController.$inject = ['$location','AuthenticationService'];
    function LoginController( $location, AuthenticationService) {
        var vm = this;
        
        vm.login = login;

        (function initController() {
            // reset login status
            AuthenticationService.ClearCredentials();
        })();
        
        function login() {
          console.log("login method executing");
          
          vm.dataLoading = true;
            AuthenticationService.Login(vm.username, vm.password, function (response) {
                if (response.success) {
                    AuthenticationService.SetCredentials(vm.username, vm.password);
                    $location.path('/home');
                } else {
                    alert(response.message);
                    vm.dataLoading = false;
                }
        });
      }
    }
})();

 

Next, we will go through the authenticationService.js where we will verify the user credentials. There are 3 functions in this service.

  1. Login: This function is invoked from login controller when login button is clicked from UI. Here, the user credentials are verified against stored values and a success or failure response is returned.
  2. SetCredentials: This function has the logic for storing the user credentials in a rootScope object and as well as in cookies in a form of Base64 encoded string. The same encoded string is even passed in the header of HTTP protocol so that credentials are passed in every request. This function is called from login controller when user’s credentials are verified on login event and are correct.
  3. ClearCredentials: It will clear stored credentials from the rootScope, cookies and from the header of the HTTP protocol. This function is called when the login page is loaded.
//authenticationService.js
(function () {
    'use strict';

    angular
        .module('app')
        .factory('AuthenticationService', AuthenticationService);

    AuthenticationService.$inject = ['$http', '$cookies', '$rootScope', '$timeout', 'UserService'];
    function AuthenticationService($http, $cookies, $rootScope, $timeout, UserService) {
        var service = {};

        service.Login = Login;
        service.SetCredentials = SetCredentials;
        service.ClearCredentials = ClearCredentials;

        return service;

        function Login(username, password, callback) {

            /* Dummy authentication for testing, uses $timeout to simulate api call
             ----------------------------------------------*/            $timeout(function () {
                var response;
                UserService.getByUsername(username)
                    .then(function (user) {
                        if (user !== null && user.password === password) {
                            response = { success: true };
                        } else {
                            response = { success: false, message: 'Username or password is incorrect' };
                        }
                        callback(response);
                    });
            }, 1000);

            /* Use this for real authentication
             ----------------------------------------------*/            //$http.post('/api/authenticate', { username: username, password: password })
            //    .success(function (response) {
            //        callback(response);
            //    });
        }

        function SetCredentials(username, password) {
            var authdata = Base64.encode(username + ':' + password);

            $rootScope.globals = {
                currentUser: {
                    username: username,
                    authdata: authdata
                }
            };

            // set default auth header for http requests
            $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata;

            // store user details in globals cookie that keeps user logged in for 1 week (or until they logout)
            var cookieExp = new Date();
            cookieExp.setDate(cookieExp.getDate() + 7);
            $cookies.putObject('globals', $rootScope.globals, { expires: cookieExp });
        }

        function ClearCredentials() {
            $rootScope.globals = {};
            $cookies.remove('globals');
            $http.defaults.headers.common.Authorization = 'Basic';
        }
    }

    // Base64 encoding service used by AuthenticationService
    var Base64 = {

        keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',

        encode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            do {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }

                output = output +
                    this.keyStr.charAt(enc1) +
                    this.keyStr.charAt(enc2) +
                    this.keyStr.charAt(enc3) +
                    this.keyStr.charAt(enc4);
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);

            return output;
        },

        decode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
            var base64test = /[^A-Za-z0-9\+\/\=]/g;
            if (base64test.exec(input)) {
                window.alert("There were invalid base64 characters in the input text.\n" +
                    "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                    "Expect errors in decoding.");
            }
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            do {
                enc1 = this.keyStr.indexOf(input.charAt(i++));
                enc2 = this.keyStr.indexOf(input.charAt(i++));
                enc3 = this.keyStr.indexOf(input.charAt(i++));
                enc4 = this.keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";

            } while (i < input.length);
            return output;
        }
    };
})();

 

Next, we will implement the user service page. In this service, we store the user details (the input values taken from the registration page) in the localStorage object and fetch from the same. Here, we have 3 public functions and 2 private functions. The public functions are:

  • get: For fetching all users. This is called from the home page to display all users.
  • getByUsername: Fetches a user object for the passed username.
  • create: Makes an entry for a new user. Before making an entry it will check for the user existence by username. If it does not exist, it will create a new entry. In case of failures, it sends a response as false.
//userService.svc.js
(function () {
    'use strict';
    
    angular.module("app")
       .service("UserService" , UserService);
    UserService.$inject = ['$timeout', '$filter', '$q'];
 
 function UserService($timeout, $filter, $q){
   
   var service = {};
   
   service.get = get;
   service.getByUsername = getByUsername;
   service.create = create;
   
   return service;
   
 function get(){
   var deferred = $q.defer();
    deferred.resolve(getUsers());
    return deferred.promise;
 }
 
 function getByUsername(username) {
    var deferred = $q.defer();
    var filtered = $filter('filter')(getUsers(), { username: username });
    var user = filtered.length ? filtered[0] : null;
    deferred.resolve(user);
    return deferred.promise;
  }
  
  function create(user){
    var deferred = $q.defer();

    // simulate api call with $timeout
    $timeout(function () {
    getByUsername(user.username)
       .then(function (duplicateUser) {
    
    if (duplicateUser !== null) {
        deferred.resolve({ success: false, message: 'Username "' + user.username + '" is already exists' });
    } else {
        var users = getUsers();
        // assign id
        var lastUser = users[users.length - 1] || { id: 0 };
        user.id = lastUser.id + 1;

        // save to local storage
        users.push(user);
        createUser(users);
        
        deferred.resolve({ success: true });
      }
    });
    }, 1000);

    return deferred.promise;
  }
 function getUsers(){
    if(!localStorage.users){
        localStorage.users = JSON.stringify([]);
   }
   return JSON.parse(localStorage.users);
 }
 
 function createUser(users){
  localStorage.users = JSON.stringify(users);
 }
}
})();

 

When the user logs in successfully, he is taken to the home.html. In this code, a div tag is used to display a welcome message with the user full name and a table to display all the registered users.

<!--home.html-->
<div class="col-md-6 col-md-offset-3">
  <h2 style="text-align:center;color:blue">Home</h2>
  <div align="right"><a href="#!/">Logout</a></div>
  <h3>Hi {{vm.currentUser.firstName + " " + vm.currentUser.lastName}}</h3>
  <div>Welcome.. You're logged in successfuly!!
  <br/>To view all the users please click on below link.</div>
  
  <div align="right">
  <a href="" ng-click="vm.showUsers = !vm.showUsers">View Users</a>
 </div>
  <div ng-if="vm.showUsers">
    <h4>Registered Users:</h4>
    <table class = "table table-striped table-bordered table-hover">
    <thead>
     <tr class = "info">
      <th>First Name</th>
      <th>Last Name</th>
      <th>Username</th>
     </tr>
    </thead>
    <tbody>
     <tr ng-repeat = "user in vm.allUsers track by $index">
       <td>{{ user.firstName }}</td>
       <td>{{ user.lastName }}</td>
       <td>{{ user.username }}</td>
     </tr>
    </tbody>
   </table>
  </div>
</div>

To get the currently logged in user details, the function loadCurrentUser() is used. To display all the user details, we use loadAllUsers() function. Code for homeController.js.

//homeController.js
(function () {
    'use strict';

    angular
        .module('app')
        .controller('HomeController', HomeController);

    HomeController.$inject = ['UserService', '$rootScope'];
    function HomeController(UserService, $rootScope) {
        var vm = this;
        
        vm.showUsers = false;
        
        vm.currentUser = null;
        vm.allUsers = [];
        
        initController();

        function initController() {
            loadCurrentUser();
            loadAllUsers();
        }
        function loadCurrentUser() {
            UserService.getByUsername($rootScope.globals.currentUser.username)
                .then(function (user) {
                    vm.currentUser = user;
                });
        }
        function loadAllUsers() {
            UserService.get()
                .then(function (users) {
                    vm.allUsers = users;
                });
        }
    }
})();

 

Next, to make UI attractive, we need to apply a stylesheet to it. Following code contains the Style.css.

.header{
  text-align:center;
  color:black;
  font-weight:bold;
  font-size:16px;
  margin:0 0 25px 0;
}

 

Let us run our application and see the output of it.

  1. Initially, when our application gets loaded, it looks like below.
  2. If the user is using this application for the first time, he needs to register himself. Without doing this he can not login to the application with any other credentials. Click on Register link to continue with the registration.
  3. You need to enter all the details and click on Register button which will save all the entered details in the local storage and it will display a success notification.
  4. If the entered username already exists in the system, it displays a notification message “Username “sample” already exists”.
  5. On successful login, it will take you to the home page. Please take a look at below.
  6. All the registered users are displayed on the home page by clicking View Users button.
  7. The logout button facilitates to log out from the current session and the user will be redirected to the login page.
  8. If the user credentials are wrong, it displays a failure message.

Preeti Dhavali

Leave a Comment

View Comments

  • hii...I m facing a issue after after registration while clicking a login.. it is not showing home page..plzz help me

  • I followed all the steps, but when I click on the html index page it won't display anything except the header and there is no styling.

  • how to check the database in this application... where i will find the database... to check what data is being saved

    • If you go through this application, there is no database being used here. It uses ngCookies.

      In the below code, app.js we have created an app module and invoked ngRoute for routing mechanism and ngCookies for storing user credentials in cookies.

    • Hi Sai,

      There is no direct link available for the source code. As of now, you can copy the code from here.

Share
Published by
Preeti Dhavali

Recent Posts

Everything You Need To Know About Create React App

The configuration of resources can be a time-consuming and difficult operation while creating a React…

4 weeks ago

Causes of CyberCrime and Preventive Measures

          Rapid technological growth and developments have provided vast areas of…

1 month ago

How Data Lineage will Improve Business Practices

How often have you thought about changing the way that you store and use data?…

1 month ago

10 Dominating Programming Language for Mobile App In 2022

Programming Languages are a set of rules that aid in transforming a concept into a…

1 month ago

What is Serverless Edge Computing? Features | Benefits

Serverless edge computing is a new technology with a lot of promise, but it can…

2 months ago

Are Your Accounts Protected Against Cyberattacks?

Do any of your passwords include personal names, date of birth, or pet names? If…

2 months ago