RxJs - Flat nested swithMaps and pass variables on Http interceptor
Your specific example can be simplified by treating the non-observables as simple variables, eg:
intercept(
  request: HttpRequest&lt;any&gt;,
  next: HttpHandler
): Observable&lt;HttpEvent&lt;any&gt;&gt; {
    
  const user = this.fireAuth.currentUser; 
  if (!user) return next.handle(request);

  const isApiUrl = request.url.startsWith(apiCloudURL);
  const token = user.getIdToken();

  if (isApiUrl) request = this.addToken(request, token);
  
  return next.handle(request).pipe(
    catchError(error =&gt; {
      if ( isApiUrl &amp;&amp; 
            token &amp;&amp; 
            error instanceof HttpErrorResponse &amp;&amp; 
            error.status === 403) {
        return this.handle403Error(request, next);
      } else {
        return throwError(error); 
      }
    })
  )
}

However, in the general case your question uncovers a couple of interesting RxJS &quot;patterns&quot;.
First let's ignore the path where there is no user.  What you end up with is a sequence of requests (ie your switchMaps), but where the result of any earlier request is any later request.  There is no completely clean solution to this in standard RxJS - a number of options are discussed in this article Aggregating RxJS Requests.  Nesting is the most common solution, which was your starting point.
I have been involved in the implementation of a utility to address this scenario.
With your example the resultant code would be:
intercept(
  request: HttpRequest&lt;any&gt;,
  next: HttpHandler
): Observable&lt;HttpEvent&lt;any&gt;&gt; {
    
  const isApiUrl = request.url.startsWith(apiCloudURL);

  return concatJoin(
    from(this.fireAuth.currentUser),
    ([user]) =&gt; from(user.getIdToken),
    ([user, token]) =&gt; {
      if (isApiUrl) request = this.addToken(request, token);
      return next.handle(request).pipe(...),
    },
  ).pipe(
    // resultant value is [user, token, result] - we just want the result
    map([,,result]) =&gt; result
  );
}

Now returning to handle the case where there is no user, in your implementation you are right, the filter would cause it to never emit a value.  There has to be a level of nesting:
intercept(
  request: HttpRequest&lt;any&gt;,
  next: HttpHandler
): Observable&lt;HttpEvent&lt;any&gt;&gt; {
    
  const isApiUrl = request.url.startsWith(apiCloudURL);

  return from(this.fireAuth.currentUser).pipe(
    switchMap(user =&gt; {  // or use the iif operator
      if (!user) return next.handle(request);

      return concatJoin(
        (from(user.getIdToken),
        ([token]) =&gt; {
          if (isApiUrl) request = this.addToken(request, token);
          return next.handle(request).pipe(...),
        },
      ).pipe(
        // resultant value is [token, result] - we just want the result
        map([,result]) =&gt; result
      );

    )
  )    
}