GitHub App Authentication via JWT token
In order to authenticate to GitHub as a GitHub App, you must use the JWT token authentication mechanism. This can be easily achieved with this library by obtaining a GitHub
instance like this:
GitHub github = new GitHubBuilder().withJwtToken("my_jwt_token").build();
Authenticating as a GitHub App lets you do a couple of things:
- You can retrieve high-level management information about your GitHub App.
- You can request access tokens for an installation of the app.
Where do I get the JWT token from?
To generate the JWT token required to authenticate as a GitHub app you have to:
- Sign the JWT token using the private key you configured on your GitHub app as described here
- Encode it using the
RS256
algorithm.
GitHub checks that the request is authenticated by verifying the token with the app's stored public key.
Converting the private key into a Java friendly format
Note: GitHub let's you download the GitHub App private key in the PEM
format which isn't natively supported by the JVM unless you leverage a third-party library such as BouncyCastle. In this guide we will convert it to DER
using the openssl
utility.
openssl pkcs8 -topk8 -inform PEM -outform DER -in ~/github-api-app.private-key.pem -out ~/github-api-app.private-key.der -nocrypt
How can I generate the JWT token?
Once you have the private key converted to the DER
format, you will need 2 more things before you are able to generate JWT tokens:
GitHub App Id:
You can obtain the GitHub App Id from your app settings webpage as shown below:
JWT library:
In order to generate the JWT, you will have to likely use a JWT library. In this guide we will use jjwt to that matter.
Having said that, add on your pom.xml
the following dependencies:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.10.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.10.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.10.5</version> <scope>runtime</scope> </dependency>
Now we have everything we need so let's generate the JWT token:
static PrivateKey get(String filename) throws Exception { byte[] keyBytes = Files.toByteArray(new File(filename)); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } static String createJWT(String githubAppId, long ttlMillis) throws Exception { //The JWT signature algorithm we will be using to sign the token SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256; long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); //We will sign our JWT with our private key Key signingKey = get("github-api-app.private-key.der"); //Let's set the JWT Claims JwtBuilder builder = Jwts.builder() .setIssuedAt(now) .setIssuer(githubAppId) .signWith(signingKey, signatureAlgorithm); //if it has been specified, let's add the expiration if (ttlMillis > 0) { long expMillis = nowMillis + ttlMillis; Date exp = new Date(expMillis); builder.setExpiration(exp); } //Builds the JWT and serializes it to a compact, URL-safe string return builder.compact(); } public static void main(String[] args) throws Exception { String jwtToken = createJWT("44435", 600000); //sdk-github-api-app-test GitHub gitHubApp = new GitHubBuilder().withJwtToken(jwtToken).build(); }
How do I get a specific app installation?
String jwtToken = createJWT("44435", 600000); //sdk-github-api-app-test GitHub gitHubApp = new GitHubBuilder().withJwtToken(jwtToken).build(); GHAppInstallation appInstallation = gitHubApp.getApp().getInstallationById(111111); // Installation Id
What next?
- Authenticating as an installation via the App Installation Token