Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I've wrapped up my REST API in an AnguarJS service that gets injected into controllers. Pretty standard, right. Now I'd like that service to intercept any 401 response and somehow trigger a logout or re-login prompt or something. The problem is: that service doesn't have access to any scope. What is the best way to broadcast that error? I've come up with a few ideas, but I'm new to Angular and am wondering if anyone can tell me the "Angular" way of doing this?

1) I could have the service act as an event pool that my AppCtrl can listen to. But this seems a bit overly complicated. So:

myService.on('logout', function() { 
    $scope.isLoggedIn = false;
});

2) I can inject the $rootScope into the service, and have the service modify isLoggedIn directly. But this just seems plain wrong. I'd like to keep clear distinctions where services service data, controllers control the scope, and directives muck with the dom.

3) Every one of my controllers could watch for a rejected promise and if the reason is a 401 error, then reach up the $scope and set isLoggedIn to false, but this option just sucks, obviously.

Any help?

Thanks.

share|improve this question
From where does the logout action need to happen? How will the user be shown a login form or be notified? Is there a redirect? – Josh David Miller Apr 2 at 21:06
@JoshDavidMiller That's a good question. Where should that happen. The whole thing is a one-page app, so no redirects. I'm imagining an isLoggedIn variable on the scope that controls an ngSwitch or something that either shows the App or a Login screen. Does that make sense? – nicholas Apr 2 at 21:14

1 Answer

up vote 2 down vote accepted

There are three components we need to get communicating; you already know there's the controller where the ngSwitch takes place and there's the API service. The third is some type of user state service that you use to manage user info. This type of service is very common in AngularJS apps. See this answer for an idea of what that service might look like.

Your API service would, on 401, tell that service that we are currently logged out. You could also use a generic $http interceptor for this, but it would affect all $http calls. Your choice here.

Your controller then only has to watch for this current state:

$scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
  $scope.isLoggedIn = isLoggedIn;
});

And your template can use ngShow on that scope variable:

<div class="login" ng-show="!isLoggedIn">
  ...
</div>

This service is also available to any controller that needs it. Your API service can even check the value before issuing any requests to prevent any unnecessary API calls if we have a priori knowledge the user isn't logged in.

There are countless variations on this that depend on your app's structure and your existing code, but hopefully this will set you on the right path.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.