I have a HTTP interceptor and before every request I check if the access token is expired, if it is, I subscribe to a http.post call from my service and then subscribe to it and when I get a new access token I call next.handle(request) like this:
this.auth.refreshAccessToken().subscribe((token: string) => {
this.auth.newAccessToken = token;
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
});
The issue is then it is throwing TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
Which makes me think I'm making that http.post call wrong right there.
EDIT 1: I haven't had the chance to test this thoroughly but so far it seems that everything works. I had a console.log before returning the whole map but it didn't fire, however, everything else worked and I update the currentUser everywhere/permissions everytime I get a new access token and that DID happen, so for all intents and purposes it seems to work, here's the updated code:
mergeMap(token => {
this.auth.newAccessToken = token;
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
})
You would not subscribe()
inside the interceptor, instead you would return an Observable<HttpEvent<any>>
. This can be done by utilizing RxJS pipeable operators ('rxjs/operators'
) such as tap (for side effects like setting newAccessToken
) and switchMap or mergeMap in combination with pipe()
, returning an observable of type Observable<HttpEvent<any>>
to satisfy the HttpInterceptor interface:
import { Injectable } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { AuthService } from './auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.auth.refreshAccessToken().pipe(
tap(token => this.auth.newAccessToken = token), // side effect to set token property on auth service
switchMap(token => { // use transformation operator that maps to an Observable<T>
const newRequest = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(newRequest);
})
);
}
}
Here is an example in action. Please check out the logs to see key information being logged out.
Hopefully that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With