Token based authentication with Silex and AngularJS

According to my last post today we’re going to create a AngularJS application that uses the Silex Backend that we create previously. The idea of this application is to use it within a Phonegap/Cordova application running in a mobile device.

The application will be show a login form if device haven’t a correct token.

Gonzalo_Login_Example_and_LoginServiceProvider_php_-_token_-____work_projects_token_

And whit a correct token:

Gonzalo_Login_Example

Nothing new under the sun, isn’t it?

Our front-end application will use AngularJS and Topcoat.

[sourcecode language=”html”]
<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org&quot; lang="es" ng-app="G">
<head>
<meta charset="utf-8"/>
<meta name="format-detection" content="telephone=no"/>
<!– WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 –>
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi"/>
<link rel="stylesheet" type="text/css" href="/bower_components/topcoat/css/topcoat-mobile-light.min.css">
<title>Gonzalo Login Example</title>
</head>
<body ng-controller="MainController">

<div ng-view class="main-content"></div>

<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>

<script src="js/app.js"></script>
<script src="js/services.js"></script>

</body>
</html>
[/sourcecode]

And our AngularJS application:

[sourcecode language=”js”]
‘use strict’;
var appControllers, G;
var host = ‘http://localhost:8080&#8217;; // server API url

appControllers = angular.module(‘appControllers’, []);
G = angular.module(‘G’, [‘ngRoute’, ‘appControllers’]);

G.run(function (httpG) {
httpG.setHost(host);
});

G.config([‘$routeProvider’, function ($routeProvider) {
$routeProvider.
when(‘/login’, {templateUrl: ‘partials/login.html’, controller: ‘LoginController’}).
when(‘/home’, {templateUrl: ‘partials/home.html’, controller: ‘HomeController’});
}]);

appControllers.controller(‘HomeController’, [‘$scope’, ‘httpG’, ‘$location’, function ($scope, httpG, $location) {
$scope.hello = function () {
httpG.get(‘/api/info’).success(function (data) {
if (data.status) {
alert("Hello " + data.info.name + " " + data.info.surname);
}
});
};

$scope.logOut = function () {
alert("Good bye!");
httpG.removeToken();
$scope.isAuthenticated = false;
$location.path(‘login’);
};
}]);

appControllers.controller(‘MainController’, [‘$scope’, ‘$location’, ‘httpG’, function ($scope, $location, httpG) {
$scope.isAuthenticated = false;

if (httpG.getToken()) {
$scope.isAuthenticated = true;
$location.path(‘home’);
} else {
$location.path(‘login’);
}
}]);

appControllers.controller(‘LoginController’, [‘$scope’, ‘$location’, ‘httpG’, function ($scope, $location, httpG) {
$scope.user = {};

$scope.doLogIn = function () {
httpG.get(‘/auth/validateCredentials’, {user: $scope.user.username, pass: $scope.user.password}).success(function (data) {
if (data.status) {
httpG.setToken(data.info.token);
$scope.isAuthenticated = true;
$location.path(‘home’);
} else {
alert("login error");
}
}).error(function (error) {
alert("Login Error!");
});
};

$scope.doLogOut = function () {
httpG.removeToken();
};
}]);
[/sourcecode]

In this example I’m using angular-route to handle the application’s routes. Nowadays I’m swaping to angular-ui-router, but this example I’m still using “old-style” routes. We define two partials:

partial/home.html
[sourcecode language=”html”]
<div class="topcoat-button-bar full" style="position: fixed; bottom: 0px;">
<label class="topcoat-button-bar__item">
<button class="topcoat-button full" ng-click="logOut()">
<span class="">Logout</span>
</button>
</label>
<label class="topcoat-button-bar__item">
<button class="topcoat-button–cta full" ng-click="hello()">
<span class="">Hello</span>
</button>
</label>
</div>
[/sourcecode]

partial/login.html
[sourcecode language=”html”]
<div class="topcoat-navigation-bar">
<div class="topcoat-navigation-bar__item center full">
<h1 class="topcoat-navigation-bar__title">Login</h1>
</div>
</div>

<ul class="topcoat-list__container">
<li class="topcoat-list__item center">
<input ng-model="user.username" class="topcoat-text-input–large" type="text" name="user"
placeholder="Username"/>
</li>
<li class="topcoat-list__item center">
<input ng-model="user.password" class="topcoat-text-input–large" type="password" name="pass"
placeholder="Password"/>
</li>
</ul>

<div class="topcoat-button-bar full" style="position: fixed; bottom: 0px;">
<label class="topcoat-button-bar__item">
<button class="topcoat-button–cta full" ng-click="doLogIn()">
<span class="">Login</span>
</button>
</label>
</div>
[/sourcecode]

As we can see in the application we’re using a service to handle Http connections with the token information.

[sourcecode language=”js”]
‘use strict’;

G.factory(‘httpG’, [‘$http’, ‘$window’, function ($http, $window) {
var serviceToken, serviceHost, tokenKey;
tokenKey = ‘token’;
if (localStorage.getItem(tokenKey)) {
serviceToken = $window.localStorage.getItem(tokenKey);
}

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

return {
setHost: function (host) {
serviceHost = host;
},

setToken: function (token) {
serviceToken = token;
$window.localStorage.setItem(tokenKey, token);
},

getToken: function () {
return serviceToken;
},

removeToken: function() {
serviceToken = undefined;
$window.localStorage.removeItem(tokenKey);
},

get: function (uri, params) {
params = params || {};
params[‘_token’] = serviceToken;
return $http.get(serviceHost + uri, {params: params});
},

post: function (uri, params) {
params = params || {};
params[‘_token’] = serviceToken;

return $http.post(serviceHost + uri, params);
}
};
}]);
[/sourcecode]

And that’s all. You can see the full example in my github account.