1
votes

I am having trouble attaching a JWT access token to the header of an HTTP request within a class which derives from the HttpInterceptor (Angular 8) base class.

I have narrowed the issue down to the sequence in which the operations are performed within the Http Interceptor. It appears the request is sent to the caller before the token is returned back from the NGRX store (async).

I am unclear how to ensure that the request is only returned back once the token has been received back from the NGRX store.

export class ServerInterceptor implements HttpInterceptor, OnDestroy {

    private state$: Observable<any>;
    private unsubscribeAll: Subject<any>;

    constructor(
        private store: Store<AuthenticationState>
    ) {
        this.unsubscribeAll = new Subject();
        this.state$ = this.store.select(getAccessToken);
    }

    ngOnDestroy(): void {
        this.unsubscribeAll.next();
        this.unsubscribeAll.complete();
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const output = next.handle(request).pipe(
            takeUntil(this.unsubscribeAll),
            withLatestFrom(
                this.store.select(selectAuthenticationState), (_action, state) => {
                    console.log(state.accessToken);
                    if (state.accessToken) {
                        request = request.clone({
                            setHeaders: {
                              Authorization: `Bearer ${state.accessToken}`
                            }
                          });
                    }
                    console.log('1');
                    return request;
                }
            ),
            switchMap((req) => {
                console.log('2');
                return next.handle(req);
            }),            
        );
        console.log('3');
        return output;
    }
}

The output of the console processes the interceptor in the sequence 3, 1 and 2. It should be processed 1, 2 and 3.

1

1 Answers

1
votes

You can consider using select operator with your selector getAccessToken, and "chain" observables.
No need to subscribe if you use first() or take(1) operators. Observable will automatically complete after one value.

Your code for HttpInterceptor could looks like below:

export class ServerInterceptor implements HttpInterceptor {

  constructor(
    private store: Store<AuthenticationState>
  ) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.store.pipe(
      select(getAccessToken),
      first(),
      mergeMap(accessToken => {

        const authReq = !!accessToken ? request.clone({
          headers: request.headers.set('Authorization', `Bearer ${accessToken}`)
        }) : request;

        return next.handle(authReq);
      })
    );
  }
}

Some resources on the subject :