Endless loop in interceptor

I created an AngularJS website working with an API. This API provides several functions, such as authentication (Oauth).

When the API returns error 401, this means that the access_token expired and needs to be updated with refresh_token .

I created an interceptor in AngularJS. Its purpose is to check whether the result returned by the API is a 401 error, and if that happens, it should update the token and then process the previous rejected request.

The problem is that the interceptor creates an infinite loop. After the second failure of the initial request, it should stop, but this is not so.

 angular.module('myApp') .factory('authInterceptor', function ($rootScope, $q, $window, $injector) { return { // If the API returns an error 'responseError' : function(rejection) { // If it a 401 if (rejection.status == 401) { var deferred = $q.defer(); $injector.get('$http').post('http://my-api.local/api/oauth/token', { grant_type : 'refresh_token', client_id : 'id', client_secret : 'secret', refresh_token : $window.sessionStorage.refresh_token }, { headers : { 'Content-Type' : 'application/x-www-form-urlencoded' }, transformRequest : function(obj) { var str = []; for(var p in obj) str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); return str.join("&"); } }) // New token request successfull .success(function(refreshResponse) { // Processing the failed request again (should fail again because I didn't saved the new tokens) $injector.get('$http')(rejection.config).success(function(data) { deferred.resolve(data); }) .error(function(error, status) { deferred.reject(); }); return deferred.promise(); }) // New token request failure .error(function(error, status) { deferred.reject(); // $location.path('users/login'); return; }); } // If it another errorenter code here else return rejection; } } }); 

So this code:

  • Starts when the first request is not executed.
  • Updates token
  • Repeats the request but fails again (<- I just want to stop it here)
  • Updates token
  • Repeats the request but does not work again
  • Updates token
  • Repeats the request but does not work again
  • etc...
+5
source share
1 answer

I worked on this in my application. Your update request should include a config / header variable, such as skipIntercept: true . Then, when you intercept this as an unsuccessful response, you can check the rejection.config.skipIntercept variable. If this is true, you go straight to $q.reject(rejection) .

Where do you have:

 if (rejection.status == 401) { 

Change it to:

 if (rejection.status == 401 && !rejection.config.skipIntercept) { 

And then over this:

  headers : { 'Content-Type' : 'application/x-www-form-urlencoded' }, 

You need to add:

  skipIntercept: true, headers: { 'Content-Type' : 'application/x-www-form-urlencoded' }, 

PS. there is an existing solution that you can use.

+5
source

All Articles