1

angular stuff is making me crazy! tha app uses Bearer authentication, there is an errorInterceptor like this

   function errorInterceptor($injector, $log, $location) {
        var inFlight = null;
        var authInterceptorServiceFactory = {};
        var _request = function (config) {
            config.headers = config.headers || {};    
            var oauthToken = $injector.get('oauthService').getAuthorizationHeader();
            if (oauthToken) {
                config.headers.Authorization = oauthToken;    
            }
            return config;
        }

        var _responseError = function (rejection) {     
            debugger        
            var deferred = $injector.get('$q').defer();
            switch(rejection.status){
                case 401:
                    console.log('401');
                    if(inFlight == null){
                        var authService = $injector.get('oauthService');
                        inFlight = authService.refreshToken() //this is just a $http call 
                    }
                    inFlight
                        .then(function (response) {
                            _retryHttpRequest(rejection.config, deferred)
                                .success(function (result) {
                                    deferred.resolve(result);
                                })
                                .error(function(err, status) {
                                    deferred.reject(err);
                                })
                                .finally(function() {                                       
                                    inFlight = null;
                                });
                            $injector.get('oauthService').setLocalStorageData(response.data);

                        },
                        function (err, status) {
                                $injector.get('oauthService').logOut();
                        });
                    break;

            } 

            return deferred.promise;
        }

        var _retryHttpRequest = function (config, deferred) {
            var $http = $http || $injector.get('$http');
            return $http(config);
        }

        authInterceptorServiceFactory.request = _request;
        authInterceptorServiceFactory.responseError = _responseError;

        return authInterceptorServiceFactory;
    }

it almost works, 1st 401 response issues a "refreshToken" request then all subsequent requests are re-sent with the new token. The problem i'm facing is in the line

deferred.resolve(result);

and although result is the expected object, when promise function is invoked its argument is undefined!

the promise function

sidebarService.getMenu()
        .success(sidebarReady)
        .error(sidebarReadyError);

function sidebarReady(items) { 
        //when errorInterceptor catches the error 
        //and re-sends, when it resolves this funciton, argument is undefined 
        // 
    }

Can anyone please help? thank you

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • I don't see where you're passing a parameter to your `sidebarReady` function. You're just setting the function as a success callback without anything be passed. – Ben Mar 22 '17 at 18:11
  • 1
    This is unrelated to your question, but you should be aware that storing your refreshtoken in localstorage may be a security liability. Since it can be accessed by JavaScript, it may be subject to potential XSS attacks. So if you want to store it in localstorage, you'll have to be absolutely certain that none of your code, and none of your libraries are susceptible to XSS. – Nikolaj Dam Larsen Mar 22 '17 at 18:28
  • Avoid the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! Just for example, when `inFlight` rejects your deferred is never settled. – Bergi Mar 22 '17 at 19:26
  • See [Why are angular $http success/error methods deprecated? Removed from v1.6?](http://stackoverflow.com/a/35331339/5535245). – georgeawg Mar 22 '17 at 22:29

2 Answers2

1

Just use .then() instead of .success(), its deprecated since Angular 1.5 anyway and got removed in 1.6. With .success() promise chaining is not possible, as it doesn't return a new promise to resolve.

Nekudotayim
  • 173
  • 5
  • since I could not test the code fragments so far I'm almost sure those promises are the main problem. [This explanation](http://blog.ninja-squad.com/2015/05/28/angularjs-promises/) helped me a lot. – Nekudotayim Mar 22 '17 at 19:16
0

it turns out that using .then() instead of .success() worked! thanks @Nekudotayim

also thanks @Ben and @Nikolay

:)