I am trying to create an error-handling method for all authentication issues. I am running into an issue where my authTokenService.getAmadeusAuthToken$ method is being called but since it's a post-call that returns a new token, it takes longer to resolve, in the meantime the catchError obvservable returns the next.handle before the token is retrieved. I have tried a few different ways and I don't know the best way to have interceptor method wait until the authTokenService.getAmadeusAuthToken$ is completed. Here is my code:
My Interceptor:
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((response: HttpErrorResponse) => {
return next.handle(req).pipe(
tap(test => {
this.authTokenService.getAmadeusAuthToken$().pipe(
).subscribe(token => {
const authReq = req.clone({
headers: req.headers.append('Authorization', 'Bearer ' + token.access_token)
});
return next.handle(authReq);
})
})
)
})
);
}
The method to post call to grab a new token
getAmadeusAuthToken$(): Observable<any> {
const httpOptions = { headers: new HttpHeaders().set('Content-Type', "application/x-www-form-urlencoded") };
return this.http.post<Token>('https://test.api.amadeus.com/v1/security/oauth2/token', this.body, httpOptions);
}
To make sure the intercept method works, I made an API call to just grab the new token and hardcoded it in. The intercept method work like a charm since there isn't a race condition and the interceptor returns the next.handle() with the token right away.
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((response: HttpErrorResponse) => {
const authReq = req.clone({
headers: req.headers.append('Authorization', 'Bearer ' + "lkVkfilWizfcuyVpXBQsA08XkUy5")
});
return next.handle(authReq);
})
);
}
So basically I want to make sure the interceptor waits for the authTokenService.getAmadeusAuthToken$
to finish getting the token, and only then return the new next.handle
with the token, what am I missing here?
This eliminates the race condition I had and makes sure the request waits for the new token response before trying the request again. This is a quick and dirty way of doing it, Further refinement will need to be done in order to cache the token in local storage and put in a filter for specific error codes
export class AuthInterceptor implements HttpInterceptor {
token : Token;
idTokenPresent = false;
authRequest: any;
idToken: string | string[] | null;
testreq: any;
constructor(private authTokenService: AuthTokenService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((response: HttpErrorResponse) => {
return this.authTokenService.getAmadeusAuthToken$().pipe(
switchMap(token => {
this.authRequest = req.clone({
headers: req.headers.append('Authorization', 'Bearer ' + token.access_token)
});
return next.handle(this.authRequest)
})
)
}
)
)
}
}