Im trying to implement this angular refresh token interceptor (also from this stackoverflow) but having trouble when changing the refreshToken function to return this.http.get observer instead of rxjs of operator.
It works correct with of, but as soon as i change to http.get return it never fires the get call and doesnt emit anything, nor goes to the next concat observer subscription.
Cant figure out why its not working. Any help appreciated.
interceptor file:
export class CaughtInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let retries = 0;
return this.authService.token$.pipe(
map(token => req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })),
concatMap(authReq => next.handle(authReq)),
// Catch the 401 and handle it by refreshing the token and restarting the chain
// (where a new subscription to this.auth.token will get the latest token).
catchError((err, restart) => {
// If the request is unauthorized, try refreshing the token before restarting.
if (err.status === 401 && retries === 0) {
retries++;
return concat(this.authService.refreshToken$, restart);
}
if (retries > 0) {
this.authService.logout();
}
return throwError(err);
})
);
}
}
auth.service file:
export interface RefreshTokenResult {
accessToken: string;
}
@Injectable()
export class AuthService {
private tokenSubject$ = new BehaviorSubject<string | null>(null);
token$ = this.tokenSubject$.pipe(
filter((token) => token !== null),
take(1)
);
refreshToken$: Observable<any> = defer(() => {
if (this.tokenSubject$.value === null) {
return this.token$;
}
// Defer allows us to easily execute some action when the Observable
// is subscribed. Here, we set the current token to `null` until the
// refresh operation is complete. This ensures no requests will be
// sent with a known bad token.
this.tokenSubject$.next(null);
return this.refreshToken().pipe(
tap((res) => {
this.tokenSubject$.next(res.accessToken);
}),
catchError((err) => {
this.logout();
throw err;
})
);
});
get token(): string | null {
return this.tokenSubject$.value;
}
authenticate(): void {
this.tokenSubject$.next('someToken');
}
refreshToken(): Observable<RefreshTokenResult> {
// Changed of to this.http.get here
return this.http.get<RefreshTokenResult>(url).pipe(delay(0));
/*
return of({
accessToken: 'newToken',
}).pipe(
delay(0),
);
*/
}
logout(): void {}
}