Authentication with AngularJS
Simplify your user authentication when using ui-router
Managing authentication within your AngularJS application is extremely important, initially I found it quite difficult to find some examples of how to do it the right way for my startup http://enquiryhq.com, keeping the logic clean, and as automated as possible.
Initially I just rolled some convoluted solution using the $rootScope to store variables, and then access those variables within my controllers, but it was messy, and created a lot of duplicate code.
So I was pointed to an article on the subject (thanks @gdi2290) that had a better example of how to do this, but it wasn’t setup for ui-router, so I had to adapt it a little to work with it.
First of all I adjusted my routes to the following: (note the addition of the authenticate property)
myApp.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state("forms", {
url: "/forms",
templateUrl: "partials/forms.html",
controller: "FormsListCtrl",
authenticate: true
})
.state("login", {
url: "/login",
templateUrl: "partials/login.html",
controller: "LoginCtrl",
authenticate: false
});
// Send to login if the URL was not found
$urlRouterProvider.otherwise("/login");
});
Then, within my run function, I’m listening to the $stateChangeStart event, which fires each time you move within your application. It’s perfect for checking authentication.
You could wrap the following code into a directive to keep it clean, but for the sake of this article I’ve included it in the run event.
angular.module("myApp")
.run(function ($rootScope, $state, AuthService) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
if (toState.authenticate && !AuthService.isAuthenticated()){
// User isn’t authenticated
$state.transitionTo("login");
event.preventDefault();
}
});
});
The AuthService is just an example service, because as well as checking if the route requires authentication, you need to also check that they are actually authenticated. In my case I have a function that checks for the existence of their token, and ensures that it’s valid.
That’s it, pretty really simple huh! It’s so much easier to maintain compared to how I was handling this before, it keeps the authentication logic much cleaner, and I don’t have to include any authentication logic in my controllers, as this handles everything.