Skip to content

Commit a96275c

Browse files
author
Marcos.Cela
committed
tests for JWTTokenProvider, verifying the "Authentication" header
This test basically ensures that the requests made with a JWTTokenProvider follow a valid Authentication pattern, verifying that the header "conforms" to a valid JWT token More information on JWT tokens can be found at: - https://jwt.io/introduction/
1 parent ca7c809 commit a96275c

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.kohsuke.github.extras.auth;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.security.GeneralSecurityException;
6+
7+
import org.junit.Test;
8+
import org.kohsuke.github.AbstractGitHubWireMockTest;
9+
import org.kohsuke.github.GitHub;
10+
11+
public class JWTTokenProviderTest extends AbstractGitHubWireMockTest {
12+
13+
private static String TEST_APP_ID_2 = "83009";
14+
private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem";
15+
16+
/**
17+
* This test will request an application ensuring that the header for the "Authorization" matches a valid JWT token.
18+
* A JWT token in the Authorization header will always start with "ey" which is always the start of the base64
19+
* encoding of the JWT Header , so a valid header will look like this:
20+
*
21+
* <pre>
22+
* Authorization: Bearer ey{rest of the header}.{payload}.{signature}
23+
* </pre>
24+
*
25+
* Matched by the regular expression:
26+
*
27+
* <pre>
28+
* ^Bearer (?<JWTHeader>ey\S*)\.(?<JWTPayload>\S*)\.(?<JWTSignature>\S*)$
29+
* </pre>
30+
*
31+
* Which is present in the wiremock matcher. Note that we need to use a matcher because the JWT token is encoded
32+
* with a private key and a random nonce, so it will never be the same (under normal conditions). For more
33+
* information on the format of a JWT token, see: https://jwt.io/introduction/
34+
*/
35+
@Test
36+
public void testAuthorizationHeaderPattern() throws GeneralSecurityException, IOException {
37+
JWTTokenProvider jwtTokenProvider = new JWTTokenProvider(TEST_APP_ID_2,
38+
new File(this.getClass().getResource(PRIVATE_KEY_FILE_APP_2).getFile()));
39+
GitHub gh = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
40+
.withAuthorizationProvider(jwtTokenProvider)
41+
.build();
42+
43+
// Request the application, the wiremock matcher will ensure that the header
44+
// for the authorization is present and has a the format of a valid JWT token
45+
gh.getApp();
46+
}
47+
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"id": 83009,
3+
"slug": "ghapi-test-app-2",
4+
"node_id": "MDM6QXBwODMwMDk=",
5+
"owner": {
6+
"login": "hub4j-test-org",
7+
"id": 7544739,
8+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
9+
"avatar_url": "https://avatars3.githubusercontent.com/u/7544739?v=4",
10+
"gravatar_id": "",
11+
"url": "https://api.github.com/users/hub4j-test-org",
12+
"html_url": "https://github.com/hub4j-test-org",
13+
"followers_url": "https://api.github.com/users/hub4j-test-org/followers",
14+
"following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}",
15+
"gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}",
16+
"starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}",
17+
"subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions",
18+
"organizations_url": "https://api.github.com/users/hub4j-test-org/orgs",
19+
"repos_url": "https://api.github.com/users/hub4j-test-org/repos",
20+
"events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}",
21+
"received_events_url": "https://api.github.com/users/hub4j-test-org/received_events",
22+
"type": "Organization",
23+
"site_admin": false
24+
},
25+
"name": "GHApi Test app 2",
26+
"description": "",
27+
"external_url": "https://localhost",
28+
"html_url": "https://github.com/apps/ghapi-test-app-2",
29+
"created_at": "2020-09-30T15:02:20Z",
30+
"updated_at": "2020-09-30T15:02:20Z",
31+
"permissions": {},
32+
"events": [],
33+
"installations_count": 1
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"id": "bb7cf5bb-45b3-fba2-afd8-939b2c24787a",
3+
"name": "app",
4+
"request": {
5+
"url": "/app",
6+
"method": "GET",
7+
"headers": {
8+
"Authorization": {
9+
"matches": "^Bearer (?<JWTHeader>ey\\S*)\\.(?<JWTPayload>\\S*)\\.(?<JWTSignature>\\S*)$"
10+
},
11+
"Accept": {
12+
"equalTo": "application/vnd.github.machine-man-preview+json"
13+
}
14+
}
15+
},
16+
"response": {
17+
"status": 200,
18+
"bodyFileName": "app-1.json",
19+
"headers": {
20+
"Date": "Thu, 05 Nov 2020 20:42:31 GMT",
21+
"Content-Type": "application/json; charset=utf-8",
22+
"Server": "GitHub.com",
23+
"Status": "200 OK",
24+
"Cache-Control": "public, max-age=60, s-maxage=60",
25+
"Vary": [
26+
"Accept",
27+
"Accept-Encoding, Accept, X-Requested-With",
28+
"Accept-Encoding"
29+
],
30+
"ETag": "W/\"b3d319dbb4dba93fbda071208d874e5ab566d827e1ad1d7dc59f26d68694dc48\"",
31+
"X-GitHub-Media-Type": "github.v3; param=machine-man-preview; format=json",
32+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
33+
"X-Frame-Options": "deny",
34+
"X-Content-Type-Options": "nosniff",
35+
"X-XSS-Protection": "1; mode=block",
36+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
37+
"Content-Security-Policy": "default-src 'none'",
38+
"X-GitHub-Request-Id": "9294:AE05:BDAC761:DB35838:5FA463B6"
39+
}
40+
},
41+
"uuid": "bb7cf5bb-45b3-fba2-afd8-939b2c24787a",
42+
"persistent": true,
43+
"insertionIndex": 1
44+
}

0 commit comments

Comments
 (0)