-
Notifications
You must be signed in to change notification settings - Fork 724
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #586 from PauloMigAlmeida/master
[Documentation] :: Add GitHub App Developer Guide
- Loading branch information
Showing
7 changed files
with
217 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Authenticating as an installation | ||
|
||
In order to authenticate to GitHub as an installation of your GitHub App, you must use the App Installation Token | ||
authentication mechanism. This can be achieved with by creating a <<<GitHub>>> instance like this: | ||
|
||
+-----+ | ||
GitHub githubAuthAsInst = new GitHubBuilder() | ||
.withAppInstallationToken(appInstallationToken.getToken()) | ||
.build(); | ||
+-----+ | ||
|
||
How do I create an App Installation Token? | ||
|
||
Assuming that you followed the {{{/githubappjwtauth.html} GitHub App Authentication via JWT token guide}} then you | ||
can create the App Installation Token like this: | ||
|
||
+-----+ | ||
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 | ||
|
||
Map<String, GHPermissionType> permissions = new HashMap<>(); | ||
permissions.put("pull_requests", GHPermissionType.WRITE); | ||
|
||
GHAppInstallationToken appInstallationToken = appInstallation | ||
.createToken(permissions) | ||
.create(); | ||
+-----+ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
GitHub App Auth Flow | ||
|
||
GitHub Apps are commonly mistaken for OAuth Apps due to their similarities but understanding the differences between | ||
them will help you decide which kind of app you want to create. | ||
|
||
In a nutshell, an OAuth App acts as a GitHub user, whereas a GitHub App uses its own identity when installed on an | ||
organization or on repositories within an organization. For a comprehensive comparision please refer to the official | ||
GitHub {{{https://developer.github.com/apps/differences-between-apps/}documentation}}. | ||
|
||
For this guide, we are going assume that you are using a GitHub App. | ||
|
||
Overview | ||
|
||
Assuming that your GitHub app has already been installed on either a user or an organization, the programmatic flow | ||
the developer must follow in order to be able to authenticate on their behalf is: | ||
|
||
[images/GitHub_App_Auth_Flow.jpg] GitHub_App_Auth_Flow | ||
|
||
Multiple <<<GitHub>>> instances will have to be created and each of them will be using a different authentication | ||
mechanism. Some actions are only accessible if you are authenticated as a GitHub App while others will only be | ||
possible if you are authenticated on behalf of a user or org. | ||
|
||
Prerequisites | ||
|
||
In order to follow this guide, you must have: | ||
|
||
* A GitHub App created as described {{{https://developer.github.com/apps/building-github-apps/creating-a-github-app/}here}} | ||
|
||
* A Private Key must be configured in your GitHub App as described {{{https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#generating-a-private-key}here}} | ||
|
||
* A User or an organisation that has already installed your GitHub App as described {{{https://developer.github.com/apps/installing-github-apps/}here}} | ||
|
||
[] | ||
|
||
What next? | ||
|
||
* Authenticating as a GitHub App via the {{{/githubappjwtauth.html}JWT Authentication}} | ||
|
||
* Authenticating as an installation via the {{{/githubappappinsttokenauth.html}App Installation Token}} | ||
|
||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
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 {{{https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#generating-a-private-key}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 {{{https://www.bouncycastle.org/}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: | ||
|
||
[images/Github_App_Id.png] Github_App_Id | ||
|
||
<<JWT library:>> | ||
|
||
In order to generate the JWT, you will have to likely use a JWT library. | ||
In this guide we will use {{{https://github.com/jwtk/jjwt}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 {{{/githubappappinsttokenauth.html}App Installation Token}} | ||
|
||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters