Я знаю, что это довольно банальный topi c, но, просмотрев довольно много решений, я не смог обновить sh мой токен jwt после получения токена refre sh. Обработчик http, который обновляет токен, по какой-то причине даже не запускается.
PS: Я также хочу повторить неудачные запросы.
Это мой server-errors.interceptor.ts файл, который обрабатывает неаутентифицированные (401) запросы.
export class ServerErrorsInterceptor implements HttpInterceptor {
isRefreshingToken = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
subscription: Subscription = null;
constructor(
private route: Router,
private toastService: ToastrService,
private authService: AuthService,
private http: HttpClient
) {}
addToken(req: HttpRequest<any>, newToken: string): HttpRequest<any> {
return req.clone({
headers: req.headers.set('Authorization', `Bearer ${newToken}`),
});
}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// If the call fails, retry until 5 times before throwing an error
return next.handle(request).pipe(
tap(
(event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// placeholder for doing stuff with event response
if (event.status == 204) {
this.toastService.error(` Wrong Credentials`, '204 Occurred', {
positionClass: 'toast-top-center',
});
}
}
},
(error: any) => {
if (error instanceof HttpErrorResponse) {
if (error.status == 401 || error.status == 403) {
this.toastService.error(
`${error.name}: ${error.status} ${error.statusText}`,
'',
{ positionClass: 'toast-top-center' }
);
// this.authService.logout();
// this.route.navigate(['']);
return this.handleUnauthorized(request, next); // for token handling
} else {
this.toastService.error(
error.error.message,
`Server Error ${error.status}`,
{ positionClass: 'toast-top-center' }
);
}
}
}
)
);
}
handleUnauthorized(
req: HttpRequest<any>,
next: HttpHandler
): Observable<any> {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
// TODO need a logic change here
const refreshToken = this.authService.getRefreshToken()
const payload = {
token: refreshToken
}
const url = 'http://202.166.161.218:8090/api/auth/refreshToken';
return this.http.post<Observable<any>>(url, payload).pipe(switchMap((newToken: any) => {
if(newToken) {
this.authService.setAccessToken(newToken.accessToken)
this.tokenSubject.next(newToken.accessToken);
req = req.clone({
setHeaders: {
'Authorization':`Bearer ${newToken.accessToken}`
}
});
return next.handle(req);
} else {
this.authService.logout();
}
this.isRefreshingToken = false;
}),
catchError(err => {
this.authService.logout();
return of(err);
}));
} else {
return this.tokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((token) => {
return next.handle(this.addToken(req, token));
})
);
}
}
}
Также стоит упомянуть, что я использую 3 перехватчика в следующем порядке:
app.module.ts
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorsInterceptor,
multi: true,
},
ApiInterceptor просто изменяет URL-адреса запросов, а JwtInterceptor проверяет наличие jwtToken.
Заранее спасибо.