0

In an angular interceptor, I want to check wether an auth-token exists. If not, it should be refreshed and the request should be resent.

return next.handle(authReq).pipe(map((result: any) => {
  if (result.body && result.body.error) {
    if (result.body.error === 'ERR_TOKEN_EXPIRED' || result.body.error === 'ERR_TOKENS_DO_NOT_MATCH') {
      console.log('Token is expired or invalid, refreshing.', result.body.error);

      return this.userService.refreshLoginToken().subscribe(success => {
        if (success) {
          return this.intercept(req, next);
        }
      });
    }
  }
  return result;
}));

The Problem is that I don't know how to replace the original Observable returned by next.handle() with a new one. The return statement before this.userService.refreshLoginToken().subscribe() returns a Subscription object. If I just pipe the result of refreshLoginToken() it wont work because refreshLoginToken sends an httprequest which is only executed when there is a subscription.

To reduce the question to a single line: How can I replace the Observable returned in line 1 by next.handle() with the one returned by this.intercept(req, next)?

Thank you!

1

1 Answer 1

1

I think you should do that a bit different way.

please check the example below and the latest switchMap:

import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {StoreState} from '@core/store';
import {select, Store} from '@ngrx/store';
import {getAuthToken} from '@v2/core/store/auth/auth.reducer';
import {iif, Observable, of} from 'rxjs';
import {switchMap, take} from 'rxjs/operators';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(protected readonly store: Store<StoreState>) {}

    public intercept(request: HttpRequest<void>, next: HttpHandler): Observable<HttpEvent<void>> {
        return this.store.pipe(
            select(getAuthToken),
            take(1),
            switchMap(token =>
                iif(
                    () => !token,
                    of(request),
                    of(
                        request.clone({
                            setHeaders: {
                                Authorization: `Bearer ${token?.accessToken}`,
                            },
                        }),
                    ),
                ),
            ),
            switchMap(clonedRequest => next.handle(clonedRequest)),
        );
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! Are the observables created by of() automatically completed when the original http observable completes?
they are completed right after they have emitted all values. but switchMap keeps listening on the main data stream until it has been completed to close the whole sequence.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.