I am trying to implement a catch for 401 responses and tried obtaining a refresh token based on Angular 4 Interceptor retry requests after token refresh. I was trying to implement the same thing, but I never was able to Retry that request, and I am really not sure if that is the best approach to apply the refresh token strategy. Here is my code:
@Injectable() export class AuthInterceptorService implements HttpInterceptor { public authService; refreshTokenInProgress = false; tokenRefreshedSource = new Subject(); tokenRefreshed$ = this.tokenRefreshedSource.asObservable(); constructor(private router: Router, private injector: Injector) { } authenticateRequest(req: HttpRequest<any>) { const token = this.authService.getToken(); if (token != null) { return req.clone({ headers: req.headers.set('Authorization', `Bearer ${token.access_token}`) }); } else { return null; } } refreshToken() { if (this.refreshTokenInProgress) { return new Observable(observer => { this.tokenRefreshed$.subscribe(() => { observer.next(); observer.complete(); }); }); } else { this.refreshTokenInProgress = true; return this.authService.refreshToken() .do(() => { this.refreshTokenInProgress = false; this.tokenRefreshedSource.next(); }).catch( (error) => { console.log(error); } ); } } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { this.authService = this.injector.get(AuthenticationService); request = this.authenticateRequest(request); return next.handle(request).do((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { // do stuff with response if you want } }, (err: any) => { if (err instanceof HttpErrorResponse) { if (err.status === 401) { return this.refreshToken() .switchMap(() => { request = this.authenticateRequest(request); console.log('*Repeating httpRequest*', request); return next.handle(request); }) .catch(() => { return Observable.empty(); }); } } }); } } The issue is that SwitchMap is never reached in...
if (err.status === 401) { return this.refreshToken() .switchMap(() => { and the do operator as well...
return this.authService.refreshToken() .do(() => { so that took me to my authService refreshToken method...
refreshToken() { let refreshToken = this.getToken(); refreshToken.grant_type = 'refresh_token'; refreshToken.clientId = environment.appSettings.clientId; return this.apiHelper.httpPost(url, refreshToken, null) .map ( response => { this.setToken(response.data, refreshToken.email); return this.getToken(); } ).catch(error => { return Observable.throw('Please insert credentials'); }); } } It returns a mapped observable, and I know it needs a subscription if I replaced the do in...
return this.authService.refreshToken() .do(() => { With subscribe I'll break the observable chain I guess. I am lost and I've playing with this for a long time without a solution. :D