-2

I'm using Angular 6 and RxJs 6.5.2. I cannot for the life of me figure out the syntax for chaining observables to add an access token to HTTP requests and return the type needed to satisfy the intercept method. I've tried all permutations of subscribe, pipe, map...

  private getApiToken(): Observable<any> {
    // TODO load from configuration
    return this.httpClient.post("https://localhost:1234/connect/token",
      {
        grant_type: "client_credentials",
        client_id: "MyClient",
        client_secret: "MySecret",
        scope: "ApiScope"
      });
  }


  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   // how do I call getApiToken here?
   return next.handle(req);
  }

Note that if I ever get this working I will of course cache the token.

Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
  • Earlier today I answered a similar question about saving auth data here: https://stackoverflow.com/a/56563234/1440240 I'd love to know if there is a better way than I'm doing with localStorage. – Ben Racicot Jun 12 '19 at 15:15
  • Marked as a duplicate with a pointer to a question without an accepted answer, the sole answer is yours, and it's a wall of cryptic code with no explanation? Really unhelpful. – Jamie Ide Jun 12 '19 at 16:27
  • I know this is probably a tough time for you but no reason to be mean. Literally trying to help you. – Ben Racicot Jun 12 '19 at 17:11
  • @BenRacicot Sorry, that was not at all directed at you, it was directed at Jota Toledo who marked this question as a duplicate. I appreciate your effort and thank you! – Jamie Ide Jun 12 '19 at 17:20
  • 1
    Ha! I appreciate the kind response, you rock! Hey About Jota, I denounced a duplicate action by him this morning also! He needs to be stopped. – Ben Racicot Jun 12 '19 at 17:33

1 Answers1

1

In order to chain these, you can do something like this

 private getApiToken(): Observable<any> {
    // TODO load from configuration
    return this.httpClient.post("https://localhost:1234/connect/token",
      {
        grant_type: "client_credentials",
        client_id: "MyClient",
        client_secret: "MySecret",
        scope: "ApiScope"
      });
  }


  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   return this.getApiToken()
     .pipe(concatMap((token) => next.handle(req)));
  }

but you are going to have to do something with the token. Here is a pattern for that which I have from a working app of mine.

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   return this.getApiToken()
     .pipe(
       concatMap((token) => {
        let headers = {
          'Authorization': `Bearer ${token}`,
        };

        const dupReq = request.clone({
            setHeaders: headers,
        });

        return next.handle(dupReq);
       }),
     );
  }

Hope that helps with your request.

That being said, I'd recommend getting the token when your app starts rather than waiting til a request is made. Usual pattern I have seen is something like get token as part of login, save that during login, if logged in grab token and add to request, if not don't add token and assume it is unauthorized request.

ccamac
  • 496
  • 2
  • 8
  • Thanks but I can't get that to compile. If I write the code almost identically to your working version, the return value is wrapped in another observable (Observable>) which doesn't match the signature of intercept. – Jamie Ide Jun 12 '19 at 15:52
  • This app needs to support both anonymous and authenticated users. Eventually my plan is to select which token to send based on if the user is authenticated but I can't even get a simple bearer token working yet. Oh, and the user could start anonymous and login at any point. Fun stuff. – Jamie Ide Jun 12 '19 at 15:54
  • @JamieIde my mistake, I think we need to use concatMap here. I'll update my answer. Please give that a shot and let me know. NOTE also realized that I had missed some parenthesis. Just tried this in my own interceptor, and I think we have it right now. – ccamac Jun 12 '19 at 16:11
  • Thank you, that got me there. I actually think I may have had this working at some point yesterday but didn't realize that the interceptor was also intercepting the call to get a token and throwing it into an endless loop. – Jamie Ide Jun 12 '19 at 17:06