Skip to content

Commit dbf6b03

Browse files
authored
Merge pull request #291 from jglick/GitHubAppCredentials.cachedToken
Cache app installation token
2 parents b55c922 + 5cb7140 commit dbf6b03

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials;
66
import edu.umd.cs.findbugs.annotations.CheckForNull;
77
import edu.umd.cs.findbugs.annotations.NonNull;
8+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
89
import hudson.Extension;
910
import hudson.Util;
1011
import hudson.util.FormValidation;
@@ -27,6 +28,7 @@
2728
import static org.jenkinsci.plugins.github_branch_source.GitHubSCMNavigator.DescriptorImpl.getPossibleApiUriItems;
2829
import static org.jenkinsci.plugins.github_branch_source.JwtHelper.createJWT;
2930

31+
@SuppressFBWarnings(value = "SE_NO_SERIALVERSIONID", justification = "XStream")
3032
public class GitHubAppCredentials extends BaseStandardCredentials implements StandardUsernamePasswordCredentials {
3133

3234
private static final String ERROR_AUTHENTICATING_GITHUB_APP = "Couldn't authenticate with GitHub app ID %s";
@@ -44,6 +46,9 @@ public class GitHubAppCredentials extends BaseStandardCredentials implements Sta
4446

4547
private String owner;
4648

49+
private transient String cachedToken;
50+
private transient long tokenCacheTime;
51+
4752
@DataBoundConstructor
4853
@SuppressWarnings("unused") // by stapler
4954
public GitHubAppCredentials(
@@ -138,7 +143,15 @@ public Secret getPassword() {
138143
apiUri = "https://api.github.com";
139144
}
140145

141-
String appInstallationToken = generateAppInstallationToken(appID, privateKey.getPlainText(), apiUri, owner);
146+
long now = System.currentTimeMillis();
147+
String appInstallationToken;
148+
if (cachedToken != null && now - tokenCacheTime < JwtHelper.VALIDITY_MS /* extra buffer */ / 2) {
149+
appInstallationToken = cachedToken;
150+
} else {
151+
appInstallationToken = generateAppInstallationToken(appID, privateKey.getPlainText(), apiUri, owner);
152+
cachedToken = appInstallationToken;
153+
tokenCacheTime = now;
154+
}
142155

143156
return Secret.fromString(appInstallationToken);
144157
}

src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@
1010
import java.security.spec.PKCS8EncodedKeySpec;
1111
import java.util.Base64;
1212
import java.util.Date;
13-
import java.util.Objects;
1413

1514
import static java.util.Objects.requireNonNull;
15+
import java.util.concurrent.TimeUnit;
1616

1717
class JwtHelper {
1818

19+
/**
20+
* Somewhat less than the <a href="https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app">maximum JWT validity</a>.
21+
*/
22+
static final long VALIDITY_MS = TimeUnit.MINUTES.toMillis(8);
23+
1924
/**
2025
* Create a JWT for authenticating to GitHub as an app installation
2126
* @param githubAppId the app ID
@@ -42,9 +47,7 @@ static String createJWT(String githubAppId, final String privateKey) {
4247
.setIssuer(githubAppId)
4348
.signWith(signingKey, signatureAlgorithm);
4449

45-
long oneMinuteInMillis = 60L * 1000L;
46-
long expMillis = nowMillis + (oneMinuteInMillis * 8);
47-
Date exp = new Date(expMillis);
50+
Date exp = new Date(nowMillis + VALIDITY_MS);
4851
builder.setExpiration(exp);
4952

5053
return builder.compact();

0 commit comments

Comments
 (0)