This is similar to the following question AngularJS - http interceptor - resend all request after token refresh and a few others on here.
Using Web Api 2, bearer tokens, TypeScript and AngularJS 1.5. Wanting to refresh my token without any user action and I have it working except for one slight issue when I go to a page with a lot of api calls (7).
When the page loads and the calls kick off, I get the 401 error. On the first 401 error I kick off a call to refresh the token and have that returned in a promise. The subsequent 4 or 5 401 calls that come in use the promise created and are waiting for the response. Once the response is there, I re-fire the calls with the new token. At this time, I get another 401 response in but since my promise is already resolved it refreshes the token again using the new refresh token i just received. And generally the same thing happens with the last call.
Looking at the calls, all the failed calls use the original token. The first refresh call will use the original token, then next refresh call with use the token returned by the previous refresh call and so on.
Not sure how relevant this is, but I'm using components and component routing and where I'm seeing this happen the page has a parent/detail setup
I'm storing the token in local storage using Angular-Local-Storage.
Any help is appreciated
Here's my interceptor:
class MyInterceptor implements ng.IHttpInterceptor {
refreshInProgress: any = null;
public static factory(tokenService: TokenService, $q: ng.IQService, $injector: ng.auto.IInjectorService) {
return new MyInterceptor(tokenService, $q, $injector);
}
constructor(private tokenService: TokenService, private $q: ng.IQService, private $injector: ng.auto.IInjectorService)
{
}
request = (config: ng.IRequestConfig): ng.IRequestConfig => {
if (this.tokenService.AmIAuthenticated()) {
config.headers = config.headers || {};
config.headers['Authorization'] = 'Bearer ' + this.tokenService.getMyTokenHere();
}
return config;
}
responseError = (responseFailure: ng.IHttpPromiseCallbackArg<any>): ng.IPromise<any> => {
if (responseFailure.status === 401) {
let deferred = this.$q.defer();
let $http: ng.IHttpService = this.$injector.get('$http');
if (!this.refreshInProgress) {
this.refreshInProgress = $http.post('api/dorefreshhere', this.tokenService.getMyRefreshTokenHere());
}
this.refreshInProgress.then((response) => {
this.refreshInProgress = null;
this.tokenService.setMyTokenHere(response.data);
$http(responseFailure.config).then(function (resp) {
deferred.resolve(resp);
}, function (reason) {
deferred.reject(reason);
});
}, (err) => {
this.refreshInProgress = null;
// redirect here
});
return deferred.promise;
}
return this.$q.reject(responseFailure);
}
}
angular.module('myapp').config(($httpProvider: ng.IHttpProvider) => {
$httpProvider.interceptors.push(MyInterceptor.factory);
});