Implement an HttpInterceptor to add and refresh a token
The following HttpInterceptor will add the authorization header and in case of getting a 403
- Will refresh the token and resubmit the original http petition
- Block the following requests while trying to refresh the to
- In case that the token cannot be refreshed it will redirect to the login page
// AuthService
export class AuthService {
estaLogeado() {}
cerrarSesion() {}
refrescarToken() {}
}
// Interceptor
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { catchError, filter, finalize, switchMap, take, tap } from 'rxjs/operators';
import { AuthService } from './auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private authService: AuthService, private router: Router) { }
private refreshTokenInProgress = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(this.agregarToken(request)).pipe(
catchError((error: any) => {
console.error('error', error);
if (request.url.includes('login') || error.status != 403) {
return throwError(error);
} else if (request.url.includes('refresh-token')) {
this.refreshTokenInProgress = false;
this.authService.cerrarSesion();
this.router.navigate(['/login']);
} else if (!this.refreshTokenInProgress) {
this.refreshTokenInProgress = true;
this.refreshTokenSubject.next(null);
// waiting
return this.authService.refrescarToken()
.pipe(
switchMap((token: string) => {
this.refreshTokenInProgress = false;
this.refreshTokenSubject.next(token);
return next.handle(this.addToken(request));
})
)
} else {
return this.refreshTokenSubject
.pipe(
filter(token => token != null),
take(1),
switchMap(token => {
return next.handle(this.addToken(request));
}),
);
}
})
)
}
addToken(request) {
if (!this.authService.estaLogeado()) {
return request;
};
return request.clone({
setHeaders: {
Authorization: `Bearer ${localStorage['token']}`
}
});
}
}