Skip to content

Commit 94588a8

Browse files
authored
Add cache for OAuth2 token to reduce the number of requests. Cache is set to expire after 5 minutes. (#997)
1 parent 1d7cbdf commit 94588a8

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/credentials/BitbucketOAuthAuthenticator.java

+25-12
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,33 @@
2525
package com.cloudbees.jenkins.plugins.bitbucket.impl.credentials;
2626

2727
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator;
28+
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketException;
29+
import com.cloudbees.jenkins.plugins.bitbucket.client.Cache;
2830
import com.cloudbees.plugins.credentials.CredentialsScope;
2931
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
3032
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
3133
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
3234
import com.github.scribejava.core.builder.ServiceBuilder;
3335
import com.github.scribejava.core.httpclient.jdk.JDKHttpClientConfig;
3436
import com.github.scribejava.core.model.OAuth2AccessToken;
37+
import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse;
3538
import com.github.scribejava.core.model.OAuthConstants;
3639
import com.github.scribejava.core.oauth.OAuth20Service;
3740
import hudson.model.Descriptor.FormException;
3841
import hudson.util.Secret;
39-
import java.io.IOException;
4042
import java.util.concurrent.ExecutionException;
43+
import java.util.concurrent.TimeUnit;
4144
import jenkins.util.SetContextClassLoader;
45+
import org.apache.commons.codec.digest.DigestUtils;
46+
import org.apache.commons.lang.StringUtils;
4247
import org.apache.http.HttpRequest;
4348

4449
public class BitbucketOAuthAuthenticator implements BitbucketAuthenticator {
50+
private static final Cache<String, OAuth2AccessToken> cacheToken = new Cache<>(5, TimeUnit.MINUTES);
4551

4652
private final String credentialsId;
4753
private final String username;
4854
private final Secret password;
49-
private OAuth2AccessToken token;
5055

5156
/**
5257
* Constructor.
@@ -60,18 +65,26 @@ public BitbucketOAuthAuthenticator(StandardUsernamePasswordCredentials credentia
6065
}
6166

6267
private OAuth2AccessToken getToken() {
63-
if (token == null) {
64-
try (SetContextClassLoader cl = new SetContextClassLoader(this.getClass());
65-
OAuth20Service service = new ServiceBuilder(username)
66-
.apiSecret(Secret.toString(password))
67-
.httpClientConfig(JDKHttpClientConfig.defaultConfig())
68-
.build(BitbucketOAuth.instance())) {
69-
token = service.getAccessTokenClientCredentialsGrant();
70-
} catch (IOException | InterruptedException | ExecutionException e) {
71-
throw new RuntimeException(e);
68+
try {
69+
String plainSecret = Secret.toString(password);
70+
String cacheKey = DigestUtils.md2Hex(StringUtils.join(new String[] { credentialsId, username, plainSecret }, '/'));
71+
return cacheToken.get(cacheKey, () -> {
72+
try (SetContextClassLoader cl = new SetContextClassLoader(this.getClass());
73+
OAuth20Service service = new ServiceBuilder(username)
74+
.apiSecret(plainSecret)
75+
.httpClientConfig(JDKHttpClientConfig.defaultConfig())
76+
.build(BitbucketOAuth.instance())) {
77+
return service.getAccessTokenClientCredentialsGrant();
78+
}
79+
});
80+
} catch (ExecutionException e) {
81+
// unwrap exception
82+
Throwable cause = e.getCause();
83+
if (cause instanceof OAuth2AccessTokenErrorResponse oauthEx) {
84+
throw new BitbucketException(oauthEx.getErrorDescription() + ". Please check configured OAuth credentials client id and secret are correct.", e);
7285
}
86+
throw new RuntimeException(cause);
7387
}
74-
return token;
7588
}
7689

7790
/**

0 commit comments

Comments
 (0)