12

I have just started out working with an AngularJS app I'm developing, everything is going well but I need a way of protecting routes so that a user wouldn't be allowed to go to that route if not logged in. I understand the importance of protecting on the service side also and I will be taking care of this.

I have found a number of ways of protecting the client, one seems to use the following:

$scope.$watch(
    function() {
        return $location.path();
    },
    function(newValue, oldValue) {
        if ($scope.loggedIn == false && newValue != '/login') {
            $location.path('/login');
        }
    }
);

Where do I need to put this, in the .run in the app.js?

And the other way I have found is using a directive and using an on - routechagestart

The info is here: http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app

What can I try next?

2
  • 1
    egghead.io (free) videos 27->39 explain the whole routing thing. It should help you. The closest video is Resolve (35) Commented Jun 20, 2013 at 9:08
  • Thanks Utopik, Yes i have already seen those. I think I am really looking for some input on the recommended way of doing the above. Commented Jun 20, 2013 at 9:18

2 Answers 2

24

Using resolves should help you out here: (code not tested)

angular.module('app' []).config(function($routeProvider){
    $routeProvider
        .when('/needsauthorisation', {
            //config for controller and template
            resolve : {
                //This function is injected with the AuthService where you'll put your authentication logic
                'auth' : function(AuthService){
                    return AuthService.authenticate();
                }
            }
        });
}).run(function($rootScope, $location){
    //If the route change failed due to authentication error, redirect them out
    $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){
        if(rejection === 'Not Authenticated'){
            $location.path('/');
        }
    })
}).factory('AuthService', function($q){
    return {
        authenticate : function(){
            //Authentication logic here
            if(isAuthenticated){
                //If authenticated, return anything you want, probably a user object
                return true;
            } else {
                //Else send a rejection
                return $q.reject('Not Authenticated');
            }
        }
    }
});
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, so if not authenticated where would i do a $location.path ? to redirect
You can do that via the $routeChangeError event thats broadcasted against the route scope when a route fails. I'll update my answer
Is there a way to do this globally for all routes?
-1 - the question was specifically about authorization, not authentication. I would use route/state change events. Add the required "role" to the route provider data (custom attribute) and do the test in the event
|
4

Another way of using the resolve attribute of the $routeProvider:

angular.config(["$routeProvider",
function($routeProvider) {

  "use strict";

  $routeProvider

  .when("/forbidden", {
    /* ... */
  })

  .when("/signin", {
    /* ... */
    resolve: {
      access: ["Access", function(Access) { return Access.isAnonymous(); }],
    }
  })

  .when("/home", {
    /* ... */
    resolve: {
      access: ["Access", function(Access) { return Access.isAuthenticated(); }],
    }
  })

  .when("/admin", {
    /* ... */
    resolve: {
      access: ["Access", function(Access) { return Access.hasRole("ADMIN"); }],
    }
  })

  .otherwise({
    redirectTo: "/home"
  });

}]);

This way, if Access does not resolve the promise, the $routeChangeError event will be fired:

angular.run(["$rootScope", "Access", "$location",
function($rootScope, Access, $location) {

  "use strict";

  $rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
    if (rejection == Access.UNAUTHORIZED) {
      $location.path("/login");
    } else if (rejection == Access.FORBIDDEN) {
      $location.path("/forbidden");
    }
  });

}]);

See the full code on this answer.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.