Search code examples
angularapolloapollo-angular

authentication await in async setContext


In the docs ( https://www.apollographql.com/docs/angular/recipes/authentication/ ) there is an example. However this does not work, if you have a angular-apollo watch().valueChanges or fetch() as returned Observable...

My code is:

const auth = setContext(async (_, {headers}) => {
      let token = authService.getAccessToken();

      if (!authService.hasValidAccessToken()) {
        if (authService.hasRefreshToken()) {
         
          await this.authService.refreshToken().pipe(first()).toPromise(); //Does not work...
          
          token = authService.getAccessToken();
        }
      }
      // Return the headers as usual
      return {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      };
    });

the authService.refreshToken() method is returning this:

refreshToken(): Observable<any> {
    this.removeAccessToken();
    if (this.hasRefreshToken()) {
      return this.refreshGQL.fetch({
         refreshToken: this.getRefreshToken()
      }).pipe(
        tap(next => {
            this.storeTokens(next.data.refresh);
          }
        )
      );
}

problem is, that one could not call subscribe, which would start the Observable. Do you have a solution?


Solution

  • ok, it had nothing todo with the await for promise and observable to promise thing. This is perfectly right.

    It was just a classic deadlock.

    If there is no valid access token, it will try to receive a new one, resulting in a gql request, wich also has no valid access token which will try to receve a new one per gql request etc...

    Solved by just skipping the logic if the operation name is equal to the refresh mutation or query.