I'm writing an angularjs client for a token based restful API. The tokens in the API expire every hour so every time the token is expired in my client there should be a refresh token action.
The controller which handles the API call results looks like this:
angular.module('apitestApp')
.controller('MainCtrl', ['$rootScope', '$scope', 'httpService', function ($rootScope, $scope, httpService) {
$scope.messages = [];
var url = $rootScope.domainPath + $rootScope.apiPath + 'messages.json';
httpService.getRequest(url, {}).then(
function (data){
$scope.messages = data;
}
);
}]);
I have a service that makes the API calls using angularjs $resource
angular.module('apitestApp')
.service('httpService', ['$rootScope', '$resource', '$localStorage', function ($rootScope, $resource, $localStorage) {
this.getRequest = function (url, params){
var res = $resource(url, params, {
query: {
method: 'GET',
isArray: true,
headers: { 'Authorization': 'Bearer ' + $localStorage.token.access_token }
}
});
return res.query().$promise;
};
this.refreshToken = function (){
var url = $rootScope.domainPath + this.authPath;
var request = $resource(url);
return request.get({
client_id: this.clientId,
client_secret: this.secret,
grant_type: 'refresh_token',
refresh_token: $localStorage.token.refresh_token
},
function (data){
$localStorage.token = data;
}
).$promise;
};
}]);
And finally an interceptor that handles all unauthorized requests (401), refresh the access token and retries the failed request.
angular.module('apitestApp')
.factory('apiInterceptor', ['$q', '$injector', function ($q, $injector){
//Handling error codes
return {
response : function (response){
return response || $q.when(response);
},
responseError: function (rejection){
switch(rejection.status){
case 400:
console.log("Bad request");
break;
case 401:
var config = rejection.config;
var deferred = $q.defer();
var httpService = $injector.get('httpService');
httpService.refreshToken().then(deferred.resolve, deferred.reject);
return deferred.promise.then(function (){
return httpService.getRequest(config.url, config.params);
});
//break;
case 500:
console.log("Internal server error");
break;
default:
console.log("Another error");
break;
}
return $q.reject(rejection);
}
};
}]);
When the access token is valid, getRequest() method in my service successfully returns a promise, this is the same I want the interceptor to return but is not. In case the access token has expired the interceptor catches a 401 error, then updates the access token and finally makes the same request, the problem is that my controller doesn't get any response of it.
How can I perform a refresh token action and return the expected data on the behalf of the user? What am I doing wrong in the interceptor?