Skip to content

Commit 0e01142

Browse files
authored
Merge pull request hub4j#586 from PauloMigAlmeida/master
[Documentation] :: Add GitHub App Developer Guide
2 parents 0e60871 + ba658f7 commit 0e01142

File tree

7 files changed

+217
-7
lines changed

7 files changed

+217
-7
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Authenticating as an installation
2+
3+
In order to authenticate to GitHub as an installation of your GitHub App, you must use the App Installation Token
4+
authentication mechanism. This can be achieved with by creating a <<<GitHub>>> instance like this:
5+
6+
+-----+
7+
GitHub githubAuthAsInst = new GitHubBuilder()
8+
.withAppInstallationToken(appInstallationToken.getToken())
9+
.build();
10+
+-----+
11+
12+
How do I create an App Installation Token?
13+
14+
Assuming that you followed the {{{/githubappjwtauth.html} GitHub App Authentication via JWT token guide}} then you
15+
can create the App Installation Token like this:
16+
17+
+-----+
18+
String jwtToken = createJWT("44435", 600000); //sdk-github-api-app-test
19+
GitHub gitHubApp = new GitHubBuilder().withJwtToken(jwtToken).build();
20+
GHAppInstallation appInstallation = gitHubApp.getApp().getInstallationById(111111); // Installation Id
21+
22+
Map<String, GHPermissionType> permissions = new HashMap<>();
23+
permissions.put("pull_requests", GHPermissionType.WRITE);
24+
25+
GHAppInstallationToken appInstallationToken = appInstallation
26+
.createToken(permissions)
27+
.create();
28+
+-----+

src/site/apt/githubappflow.apt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
GitHub App Auth Flow
2+
3+
GitHub Apps are commonly mistaken for OAuth Apps due to their similarities but understanding the differences between
4+
them will help you decide which kind of app you want to create.
5+
6+
In a nutshell, an OAuth App acts as a GitHub user, whereas a GitHub App uses its own identity when installed on an
7+
organization or on repositories within an organization. For a comprehensive comparision please refer to the official
8+
GitHub {{{https://developer.github.com/apps/differences-between-apps/}documentation}}.
9+
10+
For this guide, we are going assume that you are using a GitHub App.
11+
12+
Overview
13+
14+
Assuming that your GitHub app has already been installed on either a user or an organization, the programmatic flow
15+
the developer must follow in order to be able to authenticate on their behalf is:
16+
17+
[images/GitHub_App_Auth_Flow.jpg] GitHub_App_Auth_Flow
18+
19+
Multiple <<<GitHub>>> instances will have to be created and each of them will be using a different authentication
20+
mechanism. Some actions are only accessible if you are authenticated as a GitHub App while others will only be
21+
possible if you are authenticated on behalf of a user or org.
22+
23+
Prerequisites
24+
25+
In order to follow this guide, you must have:
26+
27+
* A GitHub App created as described {{{https://developer.github.com/apps/building-github-apps/creating-a-github-app/}here}}
28+
29+
* 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}}
30+
31+
* A User or an organisation that has already installed your GitHub App as described {{{https://developer.github.com/apps/installing-github-apps/}here}}
32+
33+
[]
34+
35+
What next?
36+
37+
* Authenticating as a GitHub App via the {{{/githubappjwtauth.html}JWT Authentication}}
38+
39+
* Authenticating as an installation via the {{{/githubappappinsttokenauth.html}App Installation Token}}
40+
41+
[]

src/site/apt/githubappjwtauth.apt

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
GitHub App Authentication via JWT token
2+
3+
In order to authenticate to GitHub as a GitHub App, you must use the JWT token authentication mechanism. This can be
4+
easily achieved with this library by obtaining a <<<GitHub>>> instance like this:
5+
6+
+-----+
7+
GitHub github = new GitHubBuilder().withJwtToken("my_jwt_token").build();
8+
+-----+
9+
10+
Authenticating as a GitHub App lets you do a couple of things:
11+
12+
* You can retrieve high-level management information about your GitHub App.
13+
14+
* You can request access tokens for an installation of the app.
15+
16+
[]
17+
18+
Where do I get the JWT token from?
19+
20+
To generate the JWT token required to authenticate as a GitHub app you have to:
21+
22+
* 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}}
23+
24+
* Encode it using the <<<RS256>>> algorithm.
25+
26+
[]
27+
28+
GitHub checks that the request is authenticated by verifying the token with the app's stored public key.
29+
30+
Converting the private key into a Java friendly format
31+
32+
<<Note:>> GitHub let's you download the GitHub App private key in the <<<PEM>>> format which isn't natively supported
33+
by the JVM unless you leverage a third-party library such as {{{https://www.bouncycastle.org/}BouncyCastle}}. In this
34+
guide we will convert it to <<<DER>>> using the <<<openssl>>> utility.
35+
36+
+-----+
37+
openssl pkcs8 -topk8 -inform PEM -outform DER -in ~/github-api-app.private-key.pem -out ~/github-api-app.private-key.der -nocrypt
38+
+-----+
39+
40+
How can I generate the JWT token?
41+
42+
Once you have the private key converted to the <<<DER>>> format, you will need 2 more things before you are able to
43+
generate JWT tokens:
44+
45+
<<GitHub App Id:>>
46+
47+
You can obtain the GitHub App Id from your app settings webpage as shown below:
48+
49+
[images/Github_App_Id.png] Github_App_Id
50+
51+
<<JWT library:>>
52+
53+
In order to generate the JWT, you will have to likely use a JWT library.
54+
In this guide we will use {{{https://github.com/jwtk/jjwt}jjwt}} to that matter.
55+
56+
Having said that, add on your <<<pom.xml>>> the following dependencies:
57+
58+
+-----+
59+
<dependency>
60+
<groupId>io.jsonwebtoken</groupId>
61+
<artifactId>jjwt-api</artifactId>
62+
<version>0.10.5</version>
63+
</dependency>
64+
<dependency>
65+
<groupId>io.jsonwebtoken</groupId>
66+
<artifactId>jjwt-impl</artifactId>
67+
<version>0.10.5</version>
68+
<scope>runtime</scope>
69+
</dependency>
70+
<dependency>
71+
<groupId>io.jsonwebtoken</groupId>
72+
<artifactId>jjwt-jackson</artifactId>
73+
<version>0.10.5</version>
74+
<scope>runtime</scope>
75+
</dependency>
76+
+-----+
77+
78+
79+
Now we have everything we need so let's generate the JWT token:
80+
81+
+-----+
82+
static PrivateKey get(String filename) throws Exception {
83+
byte[] keyBytes = Files.toByteArray(new File(filename));
84+
85+
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
86+
KeyFactory kf = KeyFactory.getInstance("RSA");
87+
return kf.generatePrivate(spec);
88+
}
89+
90+
static String createJWT(String githubAppId, long ttlMillis) throws Exception {
91+
//The JWT signature algorithm we will be using to sign the token
92+
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;
93+
94+
long nowMillis = System.currentTimeMillis();
95+
Date now = new Date(nowMillis);
96+
97+
//We will sign our JWT with our private key
98+
Key signingKey = get("github-api-app.private-key.der");
99+
100+
//Let's set the JWT Claims
101+
JwtBuilder builder = Jwts.builder()
102+
.setIssuedAt(now)
103+
.setIssuer(githubAppId)
104+
.signWith(signingKey, signatureAlgorithm);
105+
106+
//if it has been specified, let's add the expiration
107+
if (ttlMillis > 0) {
108+
long expMillis = nowMillis + ttlMillis;
109+
Date exp = new Date(expMillis);
110+
builder.setExpiration(exp);
111+
}
112+
113+
//Builds the JWT and serializes it to a compact, URL-safe string
114+
return builder.compact();
115+
}
116+
117+
public static void main(String[] args) throws Exception {
118+
String jwtToken = createJWT("44435", 600000); //sdk-github-api-app-test
119+
GitHub gitHubApp = new GitHubBuilder().withJwtToken(jwtToken).build();
120+
}
121+
+-----+
122+
123+
How do I get a specific app installation?
124+
125+
+-----+
126+
String jwtToken = createJWT("44435", 600000); //sdk-github-api-app-test
127+
GitHub gitHubApp = new GitHubBuilder().withJwtToken(jwtToken).build();
128+
GHAppInstallation appInstallation = gitHubApp.getApp().getInstallationById(111111); // Installation Id
129+
+-----+
130+
131+
What next?
132+
133+
* Authenticating as an installation via the {{{/githubappappinsttokenauth.html}App Installation Token}}
134+
135+
[]

src/site/apt/index.apt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ jwt=my_jwt_token
9393

9494
+-----+
9595
// if you are using the default configuration file
96-
GitHub github = new GitHubBuilder().fromPropertyFile().build();
96+
GitHub github = GitHubBuilder.fromPropertyFile().build();
9797

9898
// if you need to use a separate configuration file
99-
GitHub github = new GitHubBuilder().fromPropertyFile("location/my_custom_github.properties").build();
99+
GitHub github = GitHubBuilder.fromPropertyFile("location/my_custom_github.properties").build();
100100
+-----+
101101

102102
* Environmental variables
@@ -132,7 +132,7 @@ export GITHUB_JWT=my_jwt_token
132132
Once exported, you can obtain a <<<GitHub>>> instance using:
133133

134134
+-----+
135-
GitHub github = new GitHubBuilder().fromEnvironment().build();
135+
GitHub github = GitHubBuilder.fromEnvironment().build();
136136
+-----+
137137

138138

@@ -148,7 +148,7 @@ Pluggable HTTP client
148148

149149
+-----+
150150
Cache cache = new Cache(cacheDirectory, 10 * 1024 * 1024); // 10MB cache
151-
GitHub gitHub = GitHubBuilder.fromCredentials()
151+
GitHub gitHub = GitHubBuilder.fromEnvironment()
152152
.withConnector(new OkHttpConnector(new OkUrlFactory(new OkHttpClient().setCache(cache))))
153153
.build();
154154
+-----+
Loading
82.2 KB
Loading

src/site/site.xml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,21 @@
1010
<version>1.2</version>
1111
</skin>
1212

13-
1413
<body>
1514
<menu name="Git Hub API for Java">
16-
<item name="Introduction" href="/index.html"/>
17-
<item name="Download" href="http://mvnrepository.com/artifact/${project.groupId}/${project.artifactId}"/>
15+
<item name="Introduction" href="/index.html"/>
16+
<item name="Download" href="http://mvnrepository.com/artifact/${project.groupId}/${project.artifactId}"/>
1817
<item name="Source code" href="https://github.com/github-api/${project.artifactId}"/>
1918
<item name="Mailing List" href="https://groups.google.com/forum/#!forum/github-api"/>
2019
</menu>
2120

21+
<menu name="Guides">
22+
<item name="GitHub App Auth Flow" href="/githubappflow.html">
23+
<item name="JWT Authentication" href="/githubappjwtauth.html"/>
24+
<item name="App Installation Token " href="/githubappappinsttokenauth.html"/>
25+
</item>
26+
</menu>
27+
2228
<menu name="References">
2329
<item name="Javadoc" href="apidocs/index.html"/>
2430
</menu>

0 commit comments

Comments
 (0)