Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Bug: prevent concurrent access token refresh attemptsΒ #29

@chasecaleb

Description

@chasecaleb

Making multiple fetch calls using OAuth2AuthCodePKCE.decorateFetchHTTPClient(fetch) while the access token is expired will result in multiple token refresh calls. Unfortunately this causes issues such as invalid_grant error responses and potentially even rate limiting. For example, gitlab.com rate limits this particular API call to 10 requests/minute.

Here's how I worked around the issue, but it would be ideal to implement this in your library instead:

export const createGitlabOAuth = () => {
  let expiryPromise;
  let invalidGrantPromise;
  return new OAuth2AuthCodePKCE({
    authorizationUrl: 'https://gitlab.com/oauth/authorize',
    tokenUrl: 'https://gitlab.com/oauth/token',
    clientId: process.env.REACT_APP_GITLAB_CLIENT_ID,
    redirectUrl: window.location.origin,
    scopes: ['api'],
    extraAuthorizationParams: {
      clientSecret: process.env.REACT_APP_GITLAB_SECRET,
    },
    onAccessTokenExpiry: async (refreshToken) => {
      if (!expiryPromise) {
        expiryPromise = refreshToken();
      }
      const result = await expiryPromise;
      expiryPromise = undefined;
      return result;
    },
    onInvalidGrant: async (refreshAuthCodeOrToken) => {
      if (!invalidGrantPromise) {
        invalidGrantPromise = refreshAuthCodeOrToken();
      }
      // This is a void promise, so don't need to return the result. Refer to the TypeScript source
      // of OAuth2AuthCodePKCE. Types are great.
      await invalidGrantPromise;
      invalidGrantPromise = undefined;
    },
  });
};

Note: the onAccessTokenExpiry workaround was the important part for the specific scenario I encountered, but I think it makes sense to do in onInvalidGrant too.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions