Reputation: 62
When the token gets expired next: HttpHandler handle the request that comes from the server when it go inside the refershToken Subscribe method it goes to the header that I defined above the next.handle(request) and again comes to the next.handle(request) so my previous request go to the client and didn't update with the refresh token and now my existing request is /refersh-token. so after updating the token I need to double check on the button for the records or reload the page for the records.
// add authorization header with jwt token if available
refreshToken is API configuration in authenticationService class
refreshToken() {
return this.http.get<CommonResponse>(`${environment.apiUrl}/refresh-token`);
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const currentUser = this.authenticationService.currentUserValue;
if (currentUser?.token &&
!environment.publicURLS.includes(request.url.replace(environment.apiUrl, ""))
&& !this.router.url.includes("https://www.google.com/inputtools/request")) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
},
});
}
return next.handle(request).pipe(tap((data: any) => {
if (data.body?.body) {
if (data.body.body.isTokenExpired) {
this.authenticationService.refreshToken().pipe(map((res) => {
return res;
})).subscribe(res => {
if (res?.body && !res?.isError && res?.body?.token) {
const currentUser = this.authenticationService.currentUserValue;
if (currentUser) {
currentUser.token = res.body.token;
localStorage.setItem('currentUser', JSON.stringify(currentUser));
this.authenticationService.currentUserValueSubject.next(currentUser);
const retryRequest = request.clone({
setHeaders: {
Authorization: 'Bearer ' + currentUser.token,
},
});
next.handle(retryRequest);
}
}
}
);
}
if (data.body.body.isTokenInvalid) {
this.authenticationService.logout();
}
}
}
));
}
Upvotes: 2
Views: 62
Reputation: 111
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const currentUser = this.authenticationService.currentUserValue;
if (currentUser?.token && !environment.publicURLS.includes(request.url.replace(environment.apiUrl, '')) && !this.router.url.includes('https://www.google.com/inputtools/request')) {
request = this.addTokenToHeader(request, currentUser.token);
}
return next.handle(request).pipe(
mergeMap((data: HttpEvent<any>) => {
if (data instanceof HttpResponse && data.body?.body) {
if (data.body?.body?.isTokenExpired) {
return this.handleTokenRefresh(request, next);
}
if (data.body?.body?.isTokenInvalid || data.body?.body?.isAccessDenied) {
this.authenticationService.logout();
}
}
return of(data);
}),
catchError((error) => {
console.error('Error handling request:', error);
return throwError(() => error);
})
);
}
private addTokenToHeader(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
}
private handleTokenRefresh(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authenticationService.refreshToken().pipe(
switchMap((res) => {
if (res?.body && !res?.isError && res?.body?.token) {
const newToken = res.body.token;
const currentUser = this.authenticationService.currentUserValue;
if (currentUser) {
currentUser.token = newToken;
localStorage.setItem('currentUser', JSON.stringify(currentUser));
this.authenticationService.currentUserValueSubject.next(currentUser);
}
this.refreshTokenSubject.next(newToken);
return next.handle(this.addTokenToHeader(request, newToken));
}
return throwError(() => 'Refresh token failed');
}),
catchError((err) => {
return throwError(() => err);
}),
finalize(() => {
this.isRefreshing = false;
})
);
} else {
return this.refreshTokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((token) => next.handle(this.addTokenToHeader(request, token!)))
);
}
}
Upvotes: 1