2

In my angular app I need to read some data from the server before I allow the rest of my application to run. For example, I need the user authenticated so I can verify their permission before I allow them access to anything. Since I need to do this on app start and I don't know what controller will be loaded first, I can't use the resolve feature of the $routeProvider.when method because I do not know which controller will be hit first, and it only occurs once on app start.

I keep steering towards doing something in the module.run method, but I can't find a way to prevent it from continuing until get the data back from the server. I found this but it suffers from the same problem: AngularJS : Initialize service with asynchronous data.

I can also do manual bootstrapping, but I can't find any good examples of how to do this. Any help you can provide would be appreciated.

Community
  • 1
  • 1
Jason
  • 2,701
  • 2
  • 25
  • 35

2 Answers2

1

The easiest way i can think of here would be to have a separate page for login. Once the user is authenticated then only allow him access to the main app (angular app).

Also you need to secure you service resources against unauthorized request. This would safeguard against your controller \ views loading unauthorized data.

Chandermani
  • 42,589
  • 12
  • 85
  • 88
1

Like the other answer already mentioned, you should take care of the security of your app.

Possible solutions are:

Check if the user is authenticated

Implement a authentication in your API. You can check if the user is logged in with a responseInterceptor:

.config(['$routeProvider','$httpProvider', function($routeProvider,$httpProvider) {

  //setup your routes here...   

  var authChecker = ['$location', '$q', function($location, $q) {
      //redirects the user to /login page if he's not authorized (401)
      function success(response) {
          return response;
      }

      function error(response) {

          if(response.status === 401) {
              $location.path('/login');
              return $q.reject(response);
          }
          else {
              return $q.reject(response);
          }
      }

      return function(promise) {
          return promise.then(success, error);
      }
  }];

  $httpProvider.responseInterceptors.push(authChecker);
}])

See $http docs for more details.

Workaround: run scope

Does not solve the security issues, but is working, too:

Get your data in the run block like this:

.run(function($http,$location,$rootScope) {
    $rootScope.$on("$routeChangeStart", function (event, next, current) {
        if($rootScope.gotData) {
             $location.path(next.path);
        } else {
            $location.path('/loading');
        }
    });

    $http.get('path/to/data').success(function() {
        $rootScope.gotData = true;
        $location.path('/home');
    }).error(function() {
        $location.path('/404');
    })
})

see docs for further information.

ehlers
  • 690
  • 6
  • 9
  • Is there a way to hold up the app loading while waiting for the get to return? – Jason Jul 30 '13 at 19:32
  • Sure. For example, you could use a simple boolean which is set "true" in the success block of your request. Then, you can listen to $routeChangeStart in your run-block. If the boolean is false, you can redirect the user to a loading page. – ehlers Aug 02 '13 at 12:33