Skip to content

Commit 828f4d6

Browse files
authored
Merge pull request KnpLabs#439 from naderman/t/integrations
Accessing the API as an integration
2 parents 8da9b0d + 5a91711 commit 828f4d6

File tree

6 files changed

+94
-5
lines changed

6 files changed

+94
-5
lines changed

doc/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ APIs:
77
* [Enterprise](enterprise.md)
88
* [Gists](gists.md)
99
* [Comments](gists/comments.md)
10+
* [Integrations](integrations.md)
1011
* [Issues](issues.md)
1112
* [Comments](issue/comments.md)
1213
* [Labels](issue/labels.md)

doc/integrations.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
## Instegrations API
2+
[Back to the navigation](README.md)
3+
4+
Wraps [GitHub Integrations API](http://developer.github.com/v3/integrations/).
5+
6+
### Create a new installation token
7+
For the installation id 123 use the following:
8+
```php
9+
$token = $client->api('integrations')->createInstallationToken(123);
10+
```
11+
12+
To create an access token on behalf of a user with id 456 use:
13+
```php
14+
$token = $client->api('integrations')->createInstallationToken(123, 456);
15+
```

doc/security.md

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ $client->authenticate($usernameOrToken, $password, $method);
1313
```
1414

1515
`$usernameOrToken` is, of course, the username (or in some cases token/client ID, more details you can find below),
16-
and guess what should contain `$password`. The `$method` can contain one of the three allowed values:
16+
and guess what should contain `$password`. The `$method` can contain one of the five allowed values:
1717

1818
* `Github\Client::AUTH_URL_TOKEN`
1919
* `Github\Client::AUTH_URL_CLIENT_ID`
2020
* `Github\Client::AUTH_HTTP_TOKEN`
2121
* `Github\Client::AUTH_HTTP_PASSWORD`
22+
* `Github\Client::AUTH_JWT`
2223

23-
The required value of `$password` depends on the chosen `$method`. For the `Github\Client::AUTH_*_TOKEN` methods,
24-
you should provide the API token in `$username` variable (`$password` is omitted in this particular case). For the
24+
The required value of `$password` depends on the chosen `$method`. For `Github\Client::AUTH_URL_TOKEN`,
25+
`Github\Client::AUTH_HTTP_TOKEN` and `Github\Client::JWT` methods you should provide the API token in
26+
`$username` variable (`$password` is omitted in this particular case). For the
2527
`Github\Client::AUTH_HTTP_PASSWORD`, you should provide the password of the account. When using `Github\Client::AUTH_URL_CLIENT_ID`
2628
`$usernameOrToken` should contain your client ID, and `$password` should contain client secret.
2729

@@ -32,10 +34,37 @@ all further requests are done as the given user.
3234

3335
The `Github\Client::AUTH_URL_TOKEN` authentication method sends the API token in URL parameters.
3436
The `Github\Client::AUTH_URL_CLIENT_ID` authentication method sends the client ID and secret in URL parameters.
35-
The `Github_Client::AUTH_HTTP_*` authentication methods send their values to GitHub using HTTP Basic Authentication.
37+
The `Github\Client::AUTH_HTTP_*` authentication methods send their values to GitHub using HTTP Basic Authentication.
38+
The `Github\Client::AUTH_JWT` authentication method sends the specified JSON Web Token in an Authorization header.
3639

3740
`Github\Client::AUTH_URL_TOKEN` used to be the only available authentication method. To prevent existing applications
3841
from changing their behavior in case of an API upgrade, this method is chosen as the default for this API implementation.
3942

4043
Note however that GitHub describes this method as deprecated. In most case you should use the
4144
`Github\Client::AUTH_HTTP_TOKEN` instead.
45+
46+
### Authenticating as an Integration
47+
48+
To authenticate as an integration you need to supply a JSON Web Token with `Github\Client::AUTH_JWT` to request
49+
and installation access token which is then usable with `Github\Client::AUTH_HTTP_TOKEN`. [Github´s integration
50+
authentication docs](https://developer.github.com/early-access/integrations/authentication/) describe the flow in detail.
51+
It´s important for integration requests to use the custom Accept header `application/vnd.github.machine-man-preview`.
52+
53+
The following sample code authenticates as an installation using [lcobucci/jwt](https://github.com/lcobucci/jwt/tree/3.2.0)
54+
to generate a JSON Web Token (JWT).
55+
56+
```php
57+
$github = new Github\Client(new GuzzleClient(), 'machine-man-preview');
58+
59+
$jwt = (new Builder)
60+
->setIssuer($integrationId)
61+
->setIssuedAt(time())
62+
->setExpiration(time() + 60)
63+
->sign(new Sha256(), (new Keychain)->getPrivateKey($pemPrivateKeyPath))
64+
->getToken();
65+
66+
$github->authenticate($jwt, null, Github\Client::AUTH_JWT);
67+
68+
$token = $github->api('integrations')->createInstallationToken($installationId);
69+
$github->authenticate($token['token'], null, Github\Client::AUTH_HTTP_TOKEN);
70+
```

lib/Github/Api/Integrations.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Github\Api;
4+
5+
/**
6+
* @link https://developer.github.com/v3/integrations/
7+
* @author Nils Adermann <naderman@naderman.de>
8+
*/
9+
class Integrations extends AbstractApi
10+
{
11+
/**
12+
* Create an access token for an installation
13+
*
14+
* @param int $installationId An integration installation id
15+
* @param int $userId An optional user id on behalf of whom the
16+
* token will be requested
17+
*
18+
* @return array token and token metadata
19+
*/
20+
public function createInstallationToken($installationId, $userId = null)
21+
{
22+
$parameters = array();
23+
if ($userId) {
24+
$parameters['user_id'] = $userId;
25+
}
26+
27+
return $this->post('/installations/'.rawurlencode($installationId).'/access_tokens', $parameters);
28+
}
29+
}

lib/Github/Client.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ class Client
8686
*/
8787
const AUTH_HTTP_TOKEN = 'http_token';
8888

89+
/**
90+
* Constant for authentication method. Indicates JSON Web Token
91+
* authentication required for integration access to the API.
92+
*/
93+
const AUTH_JWT = 'jwt';
94+
8995
/**
9096
* @var string
9197
*/
@@ -204,6 +210,11 @@ public function api($name)
204210
$api = new Api\Gists($this);
205211
break;
206212

213+
case 'integration':
214+
case 'integrations':
215+
$api = new Api\Integrations($this);
216+
break;
217+
207218
case 'issue':
208219
case 'issues':
209220
$api = new Api\Issue($this);
@@ -293,7 +304,7 @@ public function authenticate($tokenOrLogin, $password = null, $authMethod = null
293304
throw new InvalidArgumentException('You need to specify authentication method!');
294305
}
295306

296-
if (null === $authMethod && in_array($password, array(self::AUTH_URL_TOKEN, self::AUTH_URL_CLIENT_ID, self::AUTH_HTTP_PASSWORD, self::AUTH_HTTP_TOKEN))) {
307+
if (null === $authMethod && in_array($password, array(self::AUTH_URL_TOKEN, self::AUTH_URL_CLIENT_ID, self::AUTH_HTTP_PASSWORD, self::AUTH_HTTP_TOKEN, self::AUTH_JWT))) {
297308
$authMethod = $password;
298309
$password = null;
299310
}

lib/Github/HttpClient/Plugin/Authentication.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
7171
$request = $request->withUri($uri);
7272
break;
7373

74+
case Client::AUTH_JWT:
75+
$request = $request->withHeader('Authorization', sprintf('Bearer %s', $this->tokenOrLogin));
76+
break;
77+
7478
default:
7579
throw new RuntimeException(sprintf('%s not yet implemented', $this->method));
7680
break;

0 commit comments

Comments
 (0)