private async fetchAccessToken()

in pathology/viewer/src/services/auth.service.ts [126:219]


  private async fetchAccessToken(): Promise<AppToken> {
    if (!environment.OAUTH_CLIENT_ID) {
      return Promise.resolve({
        email: '',
        oauthTokenInfo: {
          error: '',
          expirationTime: '',
          token: '',
        }
      });
    }

    const decodedToken = this.handleCredentialToken();
    if (decodedToken?.email) {
      this.userService.setCurrentUser(decodedToken.email);
    } else {
      return Promise.resolve({
        email: '',
        oauthTokenInfo: {
          error: '',
          expirationTime: '',
          token: '',
        }
      });
    }

    const tokenPromise = new Promise<AppToken>((resolve, reject) => {
      const currentUserEmailAddress =
          this.userService.getCurrentUser() ?? undefined;
      const tokenClient = google.accounts.oauth2.initTokenClient({
        client_id: environment.OAUTH_CLIENT_ID,
        scope: this.scope,
        hint: currentUserEmailAddress,
        prompt: '',
        callback: (response: google.accounts.oauth2.TokenResponse) => {
          if (response.error) {
            // User clicked cancel on the concent screen.
            const errorMessage = 'Consent needed. Access denied.';
            const error = new Error(errorMessage);
            this.logService.error(error);

            this.snackBar.open(errorMessage, 'Dismiss', this.snackBarConfig);

            this.logout();
            reject(errorMessage);
            return;
          }

          const scopes = this.scope.split(' ') as [string, ...string[]];
          if (!google.accounts.oauth2.hasGrantedAllScopes(
                  response, ...scopes)) {
            const errorMessage = 'Not all scopes are granted. Try again.';
            const error = new Error();
            this.logService.error(error);

            this.snackBar.open(errorMessage, 'Dismiss', this.snackBarConfig);

            this.logout();
            reject(errorMessage);
            return;
          }

          const token = this.convertResponseToToken(response);
          if (!token) {
            const errorMessage = 'Access denied.';
            this.logService.error(new Error(response.error));

            this.snackBar.open(errorMessage, 'Dismiss', this.snackBarConfig);

            this.logout();
            reject(response.error);
            return;
          }

          resolve(token);
        },
      });

      if (!tokenClient) {
        const errorMessage = 'No oauth client initialized.';
        this.logService.error(new Error(errorMessage));
        reject(errorMessage);
        return;
      }

      tokenClient.requestAccessToken();
    });

    const token = await tokenPromise;

    this.setCachedAccessToken(token);
    this.navigateToSearchIfAuth();
    return token;
  }