25
25
package com .cloudbees .jenkins .plugins .bitbucket .impl .credentials ;
26
26
27
27
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 ;
28
30
import com .cloudbees .plugins .credentials .CredentialsScope ;
29
31
import com .cloudbees .plugins .credentials .common .StandardUsernameCredentials ;
30
32
import com .cloudbees .plugins .credentials .common .StandardUsernamePasswordCredentials ;
31
33
import com .cloudbees .plugins .credentials .impl .UsernamePasswordCredentialsImpl ;
32
34
import com .github .scribejava .core .builder .ServiceBuilder ;
33
35
import com .github .scribejava .core .httpclient .jdk .JDKHttpClientConfig ;
34
36
import com .github .scribejava .core .model .OAuth2AccessToken ;
37
+ import com .github .scribejava .core .model .OAuth2AccessTokenErrorResponse ;
35
38
import com .github .scribejava .core .model .OAuthConstants ;
36
39
import com .github .scribejava .core .oauth .OAuth20Service ;
37
40
import hudson .model .Descriptor .FormException ;
38
41
import hudson .util .Secret ;
39
- import java .io .IOException ;
40
42
import java .util .concurrent .ExecutionException ;
43
+ import java .util .concurrent .TimeUnit ;
41
44
import jenkins .util .SetContextClassLoader ;
45
+ import org .apache .commons .codec .digest .DigestUtils ;
46
+ import org .apache .commons .lang .StringUtils ;
42
47
import org .apache .http .HttpRequest ;
43
48
44
49
public class BitbucketOAuthAuthenticator implements BitbucketAuthenticator {
50
+ private static final Cache <String , OAuth2AccessToken > cacheToken = new Cache <>(5 , TimeUnit .MINUTES );
45
51
46
52
private final String credentialsId ;
47
53
private final String username ;
48
54
private final Secret password ;
49
- private OAuth2AccessToken token ;
50
55
51
56
/**
52
57
* Constructor.
@@ -60,18 +65,26 @@ public BitbucketOAuthAuthenticator(StandardUsernamePasswordCredentials credentia
60
65
}
61
66
62
67
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 );
72
85
}
86
+ throw new RuntimeException (cause );
73
87
}
74
- return token ;
75
88
}
76
89
77
90
/**
0 commit comments