User authentication using Angularjs, PHP, Mysql

Facebook
Reddit
Twitter
Whatsapp
Cover image

I received a number of tutorial requests to publish a tutorial on user authentication. They say “Mixing PHP, MySQL, and AngularJS with Sessions and User Login, Logout, Account Creation” would be awesome”.

We will create a simple AngularJS web app that will have the following 3 functionality.

* Login, Signup and Logout.*

We will create a ReSTful web service using PHPSlim framework as data provider. The data from the ReSTful service will be used to enable user authentication in our AngularJS application.

Live Demo

To run the user authentication web application in your local machine, follow the following 3 simple steps.

  • Download the project files
  • Import angularcode_auth.sql
  • Enable rewrite_modulein apache server for friendly urls

Tutorial:

We will first create the Login page. After the user enters the correct combination of email and password, it will be authenticated from the credentials stored at our MySQL database. On successful login it will store the credentials in the user session and redirect to the welcome page. All subsequent pages browsed after login will have access to the user information.

Upon unsuccessful login or logout, the app will redirected the user to the login page.

We will use the elegant AngularJS-Toaster plugin to communicate to the user easily.

For this application we will also create some simple AngularJS directives for our SignUp form.

ReST

Representational state transfer (ReST) is a software architecture for www. Distributing the data to different kind of applications becomes convenient using this architecture. It produce status code response in JSON or XML format.

We will create following 5 folders to manage our code effectively.

api [ This directory will serve as our restful data provider ]

config.php [ Database configuration information ]
libs [ The PHPSlim library files ]
v1 [ This folder controls our API version ]
.htaccess [ used to convert urls to user friendly url]
passwordHash.php [ Generate password hash ]
dbConnect.php [ The function to connect to MySQL Database ]
dbHandler.php [ This file contains some database helper functions ]

index.php [ The starting point of the API ]
authentication.php [ Contains functions for user authentication, login, signup, session ]

appapp.js [ The main angularJS file that controls routing and authentication ]
authCtrl.js
data.js
directives.js

cssbootstrap.min.css
custom.css
toaster.css

js [ This directory contains required javascript libraries ] – angular.min.js
angular-route.min.js
angular-animate.min.js
toaster.js

partials [ Contains our partial pages that will be served based on user request ] – login.html
signup.html
dashboard.html

index.php [ Starting point of our application contains css files, javascript files and ng-view placeholder to serve all requested partial pages ]

All the API files required to create the ReSTful webservice is stored inside the “api” directory.

The only file you need to change is the “config.php” [ This file contains the database login information. Put your database credentials here ]

<?php
/**
* Database configuration
*/
define('DB_USERNAME', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('DB_NAME', 'angularcode');
?>

Also we need to import the “angularcode_auth.sql” file into our MySQL database

CREATE DATABASE IF NOT EXISTS angularcode;
USE angularcode;
--
-- Table structure for table `customers_auth`
--
CREATE TABLE IF NOT EXISTS `customers_auth` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`phone` varchar(100) NOT NULL,
`password` varchar(200) NOT NULL,
`address` varchar(50) NOT NULL,
`city` varchar(50) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=187 ;
--
-- Dumping data for table `customers_auth`
--
INSERT INTO `customers_auth` (`uid`, `name`, `email`, `phone`, `password`, `address`, `city`, `created`) VALUES
(169, 'Swadesh Behera', 'swadesh@gmail.com', '1234567890', '$2a$10$251b3c3d020155f7553c1ugKfEH04BD6nbCbo78AIDVOqS3GVYQ46', '4092 Furth Circle', 'Singapore', '2014-08-31 18:21:20'),
(170, 'Ipsita Sahoo', 'ipsita@gmail.com', '1111111111', '$2a$10$d84ffcf46967db4e1718buENHT7GVpcC7FfbSqCLUJDkKPg4RcgV2', '2, rue du Commerce', 'NYC', '2014-08-31 18:30:58'),
(171, 'Trisha Tamanna Priyadarsini', 'trisha@gmail.com', '2222222222', '$2a$10$c9b32f5baa3315554bffcuWfjiXNhO1Rn4hVxMXyJHJaesNHL9U/O', 'C/ Moralzarzal, 86', 'Burlingame', '2014-08-31 18:32:03'),
(172, 'Sai Rimsha', 'rimsha@gmail.com', '3333333333', '$2a$10$477f7567571278c17ebdees5xCunwKISQaG8zkKhvfE5dYem5sTey', '897 Long Airport Avenue', 'Madrid', '2014-08-31 20:34:21'),
(173, 'Satwik Mohanty', 'satwik@gmail.com', '4444444444', '$2a$10$2b957be577db7727fed13O2QmHMd9LoEUjioYe.zkXP5lqBumI6Dy', 'Lyonerstr. 34', 'San Francisco\n', '2014-08-31 20:36:02'),
(174, 'Tapaswini Sahoo', 'linky@gmail.com', '5555555555', '$2a$10$b2f3694f56fdb5b5c9ebeulMJTSx2Iv6ayQR0GUAcDsn0Jdn4c1we', 'ul. Filtrowa 68', 'Warszawa', '2014-08-31 20:44:54'),
(175, 'Manas Ranjan Subudhi', 'manas@gmail.com', '6666666666', '$2a$10$03ab40438bbddb67d4f13Odrzs6Rwr92xKEYDbOO7IXO8YvBaOmlq', '5677 Strong St.', 'Stavern\n', '2014-08-31 20:45:08'),
(178, 'AngularCode Administrator', 'admin@angularcode.com', '0000000000', '$2a$10$72442f3d7ad44bcf1432cuAAZAURj9dtXhEMBQXMn9C8SpnZjmK1S', 'C/1052, Bangalore', '', '2014-08-31 21:00:26');

Now our data provider is ready. Let’s create the starting point of our application (index.php)

This file contains the required stylesheet and javascript files with the placeholder to serve partial pages

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>AngularJS Authentication App</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/custom.css" rel="stylesheet">
<link href="css/toaster.css" rel="stylesheet">
<style>
a {
color: orange;
}
</style>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]><link href= "css/bootstrap-theme.css"rel= "stylesheet" >
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body ng-cloak="">
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="row">
<div class="navbar-header col-md-8">
<button type="button" class="navbar-toggle" toggle="collapse" target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" rel="home" title="AngularJS Authentication App">AngularJS Authentication App</a>
</div>
<div class="navbar-header col-md-2">
<a class="navbar-brand" rel="home" title="AngularJS Authentication Tutorial" href="http://www.angularcode.com/user-authentication-using-angularjs-php-mysql">Tutorial</a>
</div>
<div class="navbar-header col-md-2">
<a class="navbar-brand" rel="home" title="Download" href="https://app.box.com/s/1uvn9xo9nbi4xxm9g9dx">Download</a>
</div>
</div>
</div>
</div>
<div >
<div class="container" style="margin-top:20px;">
<div data-ng-view="" id="ng-view" class="slide-animation"></div>
</div>
</body>
<toaster-container toaster-options="{'time-out': 3000}"></toaster-container>
<!-- Libs -->
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/angular-animate.min.js" ></script>
<script src="js/toaster.js"></script>
<script src="app/app.js"></script>
<script src="app/data.js"></script>
<script src="app/directives.js"></script>
<script src="app/authCtrl.js"></script>
</html>

We will create and store all our custom AngularJS code files inside the app/ directory

app/ app.js

This is the starting point of our AngularJS application. Here we will load the modules and configure the route provider.

var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'toaster']);
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/login', {
title: 'Login',
templateUrl: 'partials/login.html',
controller: 'authCtrl'
})
.when('/logout', {
title: 'Logout',
templateUrl: 'partials/login.html',
controller: 'logoutCtrl'
})
.when('/signup', {
title: 'Signup',
templateUrl: 'partials/signup.html',
controller: 'authCtrl'
})
.when('/dashboard', {
title: 'Dashboard',
templateUrl: 'partials/dashboard.html',
controller: 'authCtrl'
})
.when('/', {
title: 'Login',
templateUrl: 'partials/login.html',
controller: 'authCtrl',
role: '0'
})
.otherwise({
redirectTo: '/login'
});
}])
.run(function ($rootScope, $location, Data) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$rootScope.authenticated = false;
Data.get('session').then(function (results) {
if (results.uid) {
$rootScope.authenticated = true;
$rootScope.uid = results.uid;
$rootScope.name = results.name;
$rootScope.email = results.email;
} else {
var nextUrl = next.$$route.originalPath;
if (nextUrl == '/signup' || nextUrl == '/login') {
} else {
$location.path("/login");
}
}
});
});
});

app / data.js

We will communicate with our ReSTful API using this file. This file contains some helper functions and acts as our service provider.

AngularJS Service

Sometimes while building our AngularJS application, we need some variables or functions to be accessed throughout our application from any controller. Here comes the role of AngularJS Service. As AngularJS Service services are single-tone, the defined properties and functions can be accessed from anywhere.

app.factory("Data", ['$http', 'toaster',
function ($http, toaster) { // This service connects to our REST API
var serviceBase = 'api/v1/';
var obj = {};
obj.toast = function (data) {
toaster.pop(data.status, "", data.message, 10000, 'trustedHtml');
}
obj.get = function (q) {
return $http.get(serviceBase + q).then(function (results) {
return results.data;
});
};
obj.post = function (q, object) {
return $http.post(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.put = function (q, object) {
return $http.put(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.delete = function (q) {
return $http.delete(serviceBase + q).then(function (results) {
return results.data;
});
};
return obj;
}]);

app /authCtrl.js

This is the controller which communicates with our front end.

app.controller('authCtrl', function ($scope, $rootScope, $routeParams, $location, $http, Data) {
//initially set those objects to null to avoid undefined error
$scope.login = {};
$scope.signup = {};
$scope.doLogin = function (customer) {
Data.post('login', {
customer: customer
}).then(function (results) {
Data.toast(results);
if (results.status == "success") {
$location.path('dashboard');
}
});
};
$scope.signup = {email:'',password:'',name:'',phone:'',address:''};
$scope.signUp = function (customer) {
Data.post('signUp', {
customer: customer
}).then(function (results) {
Data.toast(results);
if (results.status == "success") {
$location.path('dashboard');
}
});
};
$scope.logout = function () {
Data.get('logout').then(function (results) {
Data.toast(results);
$location.path('login');
});
}
});

app / directives.js

This file contains 2 custom AngularJS directives we used for our application.

focus – This directive focus on the desired form element on page load

password-match – Used to check if both the password and confirm password are same in our user signup page.

app.directive('focus', function() {
return function(scope, element) {
element[0].focus();
}
});
app.directive('passwordMatch', [function () {
return {
restrict: 'A',
scope:true,
require: 'ngModel',
link: function (scope, elem , attrs,control) {
var checker = function () {
//get the value of the first password
var e1 = scope.$eval(attrs.ngModel);
//get the value of the other password
var e2 = scope.$eval(attrs.passwordMatch);
if(e2!=null)
return e1 == e2;
};
scope.$watch(checker, function (n) {
//set the form control to valid if both
//passwords are the same, else invalid
control.$setValidity("passwordNoMatch", n);
});
}
};
}]);

AngularJS Directives

Directives are one of the most powerful part of the AngularJS framework. Using these we can create or extend the html elements.

We can extensively use these AngularJS directives to create templates, to validate forms, etc.

In AngularJS, it is always recommended to manipulate the DOM using directives only.


Are you looking for a job in the field of AngularJS? Find Web application developer jobs quickly

Subscribe my updates via Email