проблема. Когда я делаю недействительным токен refre sh на сервере и приходит запрос токена refre sh, я получаю следующее предупреждение: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
Это действительно происходит, когда запрос не выполняется с 401 Unauthorized. Сложная часть, которая, вероятно, неправильна, здесь:
catchError((error: any) => {
this.convertErrorToAppError(error);
return of(null);
})
На самом деле, мне здесь не нужно catchError, я хочу, чтобы произошла ошибка 401 - она должна быть перехвачена на верхнем уровне перехватчика используя метод convertErrorToAppError
. И это работает, но выдает предупреждение (You provided 'undefined'...
) как ошибку вместо Unauthorized
.
import {
HttpRequest,
HttpHandler,
HttpInterceptor,
HttpErrorResponse
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError, of } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
// import { ToastsService } from '../services/toasts';
import { AuthService } from '../services/auth.service';
// Errors
import { BadRequest } from '../errors/response-errors/bad-request';
import { NotAcceptable } from '../errors/response-errors/not-acceptable';
import { NotFound } from '../errors/response-errors/not-found';
import { Unauthorized } from '../errors/response-errors/unauthorized';
import { AppError } from '../errors/app-error';
import { NoConnection } from '../errors/no-connection';
import { Store } from '@ngxs/store';
import { SaveAccessAndRefreshTokens } from '../store/auth/actions';
import { AuthModel } from '../store/auth/model';
import { NewAccessTokenResponse } from '../store/auth/interfaces/new-access-token-response';
import { JwtHelperService } from '@auth0/angular-jwt';
import { UiService } from '../services/ui.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService,
private store: Store,
private uiService: UiService
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
return this.handle(req, next).pipe(
catchError((error: any) => {
this.convertErrorToAppError(error);
return of(null);
})
);
}
private handle(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
// If request does not have authorization header then pass it
if (
!req.headers.get('authorization') ||
req.url.endsWith('/renew-access-token') ||
req.url.endsWith('/login')
) {
return next.handle(req);
}
return this.store
.selectOnce((state: any) => {
return state.auth;
})
.pipe(
mergeMap((state: AuthModel) => {
if (state.token) {
const jwtHelper = new JwtHelperService();
if (!jwtHelper.isTokenExpired(state.token)) {
return next.handle(req);
} else {
console.log('renewAccessToken 1');
return this.authService.renewAccessToken(state.refreshToken).pipe(
mergeMap((response: NewAccessTokenResponse) => {
this.store.dispatch(new SaveAccessAndRefreshTokens(response));
const newReq = req.clone({
setHeaders: {
authorization: 'Bearer ' + response.token
}
});
return next.handle(newReq);
}),
catchError((error: any) => {
this.convertErrorToAppError(error);
return of(null);
})
);
}
}
}),
catchError((error: any) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
// JWT expired, go to login
if (error.error.message === 'Expired JWT Token') {
return this.store
.selectOnce((state: any) => {
return state.auth;
})
.pipe(
mergeMap((state: AuthModel) => {
console.log('renewAccessToken 2');
return this.authService
.renewAccessToken(state.refreshToken)
.pipe(
mergeMap((response: NewAccessTokenResponse) => {
this.store.dispatch(
new SaveAccessAndRefreshTokens(response)
);
const newReq = req.clone({
setHeaders: {
authorization: 'Bearer ' + response.token
}
});
return next.handle(newReq);
})
);
})
);
}
}
}
})
);
}
private convertErrorToAppError(error: any) {
if (error instanceof HttpErrorResponse) {
this.uiService.dismissLoading();
if (error.status === 401) {
// return throwError(new Unauthorized());
throw new Unauthorized();
}
if (error.status === 400) {
throw new BadRequest(error);
// return throwError(new BadRequest(error));
}
if (error.status === 404) {
throw new NotFound();
// return throwError(new NotFound());
}
if (error.status === 406) {
throw new NotAcceptable();
// return throwError(new NotAcceptable());
}
if (error.status === 0) {
console.error('Connection error...');
throw new NoConnection();
// return throwError(new NoConnection());
}
// return throwError(new AppError(error));
}
throw new AppError(error);
}
}