Protect authentication routes in Angular UI Router and Satellizer

Pete Houston
2 min readNov 21, 2015

--

In a typical web application, there requires to protected many routes from users. For example, protected admin routes from normal users, or users must have logged in to view the contents …

For UI Router, we will make use of the resolve property to do this. The concept is similar in backend, which is usually known as Middleware. I work with Laravel much, therefore, it is very familiar with me.

Let’s take a simple example, we have a small web app with two states with conditions:

  • login: if user is already logged in, this state should not be displayed.
  • home: if user has not logged in yet, redirect to the login state.

Depending on authentication mechanism, that we will create the appropriate check on state resolve. I will use JSON Web Token and Satellizer to demonstrate this.

angular.module(‘app’, [‘ui.router’, ‘satellizer’]).config(function ($stateProvider, $urlRouterProvider, $authProvider) {
$stateProvider
.state(‘login’, {
url: ‘/login’,
templateUrl: ‘…’,
resolve: {
skipIfAuthenticated: _skipIfAuthenticated
},
controller: ‘LoginCtrl as login’
})
.state(‘home’, {
url: ‘/home’,
templateUrl: ‘…’,
resolve: {
redirectIfNotAuthenticated: _redirectIfNotAuthenticated
},
controller: ‘HomeCtrl as home’
})
})

We will need to create two functions _redirectIf*** to handle to the authentication check that will return a promise.

function _skipIfAuthenticated($q, $state, $auth) {
var defer = $q.defer();
if($auth.authenticate()) {
defer.reject(); /* (1) */
} else {
defer.resolve(); /* (2) */
}
return defer.promise;
}

function _redirectIfNotAuthenticated($q, $state, $auth) {
var defer = $q.defer();
if($auth.authenticate()) {
defer.resolve(); /* (3) */
} else {
$timeout(function () {
$state.go(‘login’); /* (4) */
});
defer.reject();
}
return defer.promise;
}
  • (1), at this point, if user is already authenticated, there is no need to open this state, so just reject(). Otherwise, resolve() at (2), which means it is okay to launch this login state if user not authenticated.
  • (3), if user is already authenticated and want to access home state, it is fine to resolve(); otherwise, just redirect user and reject(). Important: because we are trying to redirect user state while it is still under resolving process of a state, we need to make it asynchronous by wrapping around a $timeout() as I demonstrate above; or else, it will hang in that processing state forever, which results in a blank empty page. Don’t forget this point!

That’s it, simple and effective as far as I experienced.

Have fun :)

--

--