0

I have an application for which I created an interceptor to handle token expirations after 15 minute inactivity, it successfully redirects to the login page after a token has expired, but Im not able to show the error after redirecting to the login page.

My question is, how can I show the user the token expired error on the login page, after the interceptor has redirected the app to that page.

Heres my redirector:

    app
    .config(['$httpProvider', function($httpProvider) {
        $httpProvider.interceptors.push(function($q, $location, LoopBackAuth) {
            return {
                responseError: function(rejection) {
                    if (rejection.status == 401) {
                        //Now clearing the loopback values from client browser for safe logout...
                        LoopBackAuth.clearUser();
                        LoopBackAuth.clearStorage();
                        $location.path("/login");
                    }
                    return $q.reject(rejection);
                }
            };
        })
    }])
    .config(function(LoopBackResourceProvider) {    
        LoopBackResourceProvider.setAuthHeader('X-Access-Token');
    })
maumercado
  • 1,453
  • 4
  • 23
  • 47
  • Is the `/login` path part of the primary application? Does it share the same index.html? If so, you could do a transition to the other page with a `$stateParams.error = 'Token expired'` and then show it above the login form, in a popup, whatever. You could also make the error a url parameter: `/login?error=TokenExpired`. – forrestmid Jun 15 '16 at 01:02
  • @forrestmid my other problem is my lack of knowledge of angularjs... I tried sending the error as a url parameter, and I set the scope in the login controller but I cannot reflect that error on the template when doing location.path('login').search(params), but only when reloading the login?error=xxxx page, as if location.path did not create a get request for that page. – maumercado Jun 15 '16 at 16:56
  • also no idea how to transition and add $stateParams, tried it but kept encountering a cant call method transition of undefined... since scope is not a var in the interceptor... again my lack of angularjs knowledge here might be the sole reason – maumercado Jun 15 '16 at 16:59
  • @forrestmid thank you, finally managed to do what you suggested via url params :) I will add my answer here. – maumercado Jun 15 '16 at 18:11
  • I can add an answer which involves $state transitions for you if you need it. Might be cleaner. – forrestmid Jun 15 '16 at 18:52
  • @forrestmid that would be awesome :) thank you – maumercado Jun 15 '16 at 21:34

2 Answers2

0

Finally and thanks to @forrestmid to point me in the right direction this is what I ended up doing.

on the http interceptor just added:

$location.path("/login").search({error: 'invalid_token'});

and then on the controller just had to do:

var queryString = $location.search();
$scope.errors = {};
if (queryString && queryString.error) {
    $scope.errors = {
        'invalid_token': {
            code: 'invalid_token'
        }
    }
}

now on the template I already have logic to handle the error object so now it works fine :)

maumercado
  • 1,453
  • 4
  • 23
  • 47
0

Referencing this post in regards to injecting the $state service into an HTTP interceptor:

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push(function($q, $injector, LoopBackAuth) {
        return {
            responseError: function(rejection) {
                if (rejection.status == 401) {
                    //Now clearing the loopback values from client browser for safe logout...
                    LoopBackAuth.clearUser();
                    LoopBackAuth.clearStorage();
                    $injector.get('$state').go('app.login', {error: 'Token expired.'});
                }
                return $q.reject(rejection);
            }
        };
    })
}]);

Assuming that you're using ui.router:

app.config(function($stateProvider){
    $stateProvider
       .state("app",{abstract: true})
       .state("app.login", {
           url: "/login",
           params: {error: ""}
       });
});

By default there will be no error when transitioning to the app.login state, but when there is a param error set to whatever, it can display the error. This will be in the $stateParams.error variable on your login page.

Let me know if I botched any of that code since I didn't test it. The line I think you want is the $injector line.

Community
  • 1
  • 1
forrestmid
  • 1,494
  • 17
  • 25