Skip to content

Commit

Permalink
Fix GitLab OAuth token refresh
Browse files Browse the repository at this point in the history
Prevent multiple concurrent token refresh calls if multiple GitLab API
calls are triggered while token is expired.

For more info, see issue I submitted here:
BitySA/oauth2-auth-code-pkce#29

Fixes 200ok-ch#739.
  • Loading branch information
chasecaleb committed Nov 3, 2021
1 parent 891716b commit a65eebe
Showing 1 changed file with 25 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/sync_backend_clients/gitlab_sync_backend_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import { getPersistedField } from '../util/settings_persister';

import { fromJS, Map } from 'immutable';

export const createGitlabOAuth = () =>
new OAuth2AuthCodePKCE({
export const createGitlabOAuth = () => {
// Use promises as mutex to prevent concurrent token refresh attempts, which causes problems.
// More info: https://github.com/BitySA/oauth2-auth-code-pkce/issues/29
// TODO: remove this workaround if/when oauth2-auth-code-pkce fixes the issue.
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,
Expand All @@ -15,9 +20,25 @@ export const createGitlabOAuth = () =>
extraAuthorizationParams: {
clientSecret: process.env.REACT_APP_GITLAB_SECRET,
},
onAccessTokenExpiry: (refreshToken) => refreshToken(),
onInvalidGrant: (refreshAuthCodeOrToken) => refreshAuthCodeOrToken(),
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;
},
});
};

/**
* Convert project URL to identifier for use with API, since explaining how to find the ID of a
Expand Down

0 comments on commit a65eebe

Please sign in to comment.