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 AngularJS. This 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
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.
//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:
//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.
Do you know how GPS technology works? If not, don't worry – you're not alone!…
One of today's essential necessities is having access to the internet. Its importance is no…
The marketing industry is continually evolving with new strategies and technologies catalyzing growth. To understand…
Cyber security is becoming increasingly critical as we move into the digital age. As the…
The configuration of resources can be a time-consuming and difficult operation while creating a React…
Rapid technological growth and developments have provided vast areas of…
View Comments
Can we use a different database?
Yes. You can.
Also, I am trying to learn angularJS and recreate the app step by step. But I have no clue how .$inject is being utilized. I just know the basics..
Do you have a tutorial for PHP/MySQL method? I use AngularJS 1.7.2
AWESOME INFORMATION