diff --git a/doc/security.md b/doc/security.md index afc1adeef52..174300bb573 100644 --- a/doc/security.md +++ b/doc/security.md @@ -15,11 +15,16 @@ $client->authenticate($usernameOrToken, $password, $method); `$usernameOrToken` is, of course, the username (or in some cases token/client ID, more details you can find below), and guess what should contain `$password`. The `$method` can contain one of the five allowed values: -* `Github\Client::AUTH_URL_TOKEN` -* `Github\Client::AUTH_URL_CLIENT_ID` -* `Github\Client::AUTH_HTTP_TOKEN` -* `Github\Client::AUTH_HTTP_PASSWORD` -* `Github\Client::AUTH_JWT` +#### Deprecated methods +* `Github\Client::AUTH_URL_TOKEN` use `Github\Client::AUTH_ACCESS_TOKEN` instead. +* `Github\Client::AUTH_URL_CLIENT_ID` use `Github\Client::AUTH_CLIENT_ID` instead. +* `Github\Client::AUTH_HTTP_TOKEN` use `Github\Client::AUTH_ACCESS_TOKEN` instead. +* `Github\Client::AUTH_HTTP_PASSWORD` use `Github\Client::AUTH_ACCESS_TOKEN` instead. + +#### Supported methods +* `Github\Client::AUTH_CLIENT_ID` - https://developer.github.com/v3/#oauth2-keysecret +* `Github\Client::AUTH_ACCESS_TOKEN` - https://developer.github.com/v3/#oauth2-token-sent-in-a-header +* `Github\Client::AUTH_JWT` - https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app The required value of `$password` depends on the chosen `$method`. For `Github\Client::AUTH_URL_TOKEN`, `Github\Client::AUTH_HTTP_TOKEN` and `Github\Client::JWT` methods you should provide the API token in diff --git a/lib/Github/Client.php b/lib/Github/Client.php index e20df96a039..2052461335d 100644 --- a/lib/Github/Client.php +++ b/lib/Github/Client.php @@ -72,30 +72,48 @@ class Client /** * Constant for authentication method. Indicates the default, but deprecated * login with username and token in URL. + * + * @deprecated Use `Client::AUTH_ACCESS_TOKEN` instead. See https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/#authenticating-using-query-parameters */ const AUTH_URL_TOKEN = 'url_token'; /** * Constant for authentication method. Not indicates the new login, but allows * usage of unauthenticated rate limited requests for given client_id + client_secret. + * + * @deprecated Use `Client::AUTH_CLIENT_ID` instead. See https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/#authenticating-using-query-parameters */ const AUTH_URL_CLIENT_ID = 'url_client_id'; /** * Constant for authentication method. Indicates the new favored login method * with username and password via HTTP Authentication. + * + * @deprecated Use `Client::AUTH_ACCESS_TOKEN` instead. See https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/#authenticating-using-query-parameters */ const AUTH_HTTP_PASSWORD = 'http_password'; /** * Constant for authentication method. Indicates the new login method with * with username and token via HTTP Authentication. + * + * @deprecated Use `Client::AUTH_ACCESS_TOKEN` instead. */ const AUTH_HTTP_TOKEN = 'http_token'; + /** + * Authenticate using a client_id/client_secret combination. + */ + const AUTH_CLIENT_ID = 'client_id_header'; + + /** + * Authenticate using a GitHub access token. + */ + const AUTH_ACCESS_TOKEN = 'access_token_header'; + /** * Constant for authentication method. Indicates JSON Web Token - * authentication required for integration access to the API. + * authentication required for GitHub apps access to the API. */ const AUTH_JWT = 'jwt'; diff --git a/lib/Github/HttpClient/Plugin/Authentication.php b/lib/Github/HttpClient/Plugin/Authentication.php index 0ab09ab20ba..06c593bb99f 100644 --- a/lib/Github/HttpClient/Plugin/Authentication.php +++ b/lib/Github/HttpClient/Plugin/Authentication.php @@ -34,6 +34,8 @@ public function doHandleRequest(RequestInterface $request, callable $next, calla { switch ($this->method) { case Client::AUTH_HTTP_PASSWORD: + @trigger_error('Using the "Client::AUTH_HTTP_PASSWORD" authentication method is deprecated in knp-labs/php-github-api v2.15 and will be removed in knp-labs/php-github-api v3.0. Use "Client::AUTH_ACCESS_TOKEN" instead.', E_USER_DEPRECATED); + case Client::AUTH_CLIENT_ID: $request = $request->withHeader( 'Authorization', sprintf('Basic %s', base64_encode($this->tokenOrLogin.':'.$this->password)) @@ -41,10 +43,14 @@ public function doHandleRequest(RequestInterface $request, callable $next, calla break; case Client::AUTH_HTTP_TOKEN: + @trigger_error('Using the "Client::AUTH_HTTP_TOKEN" authentication method is deprecated in knp-labs/php-github-api v2.15 and will be removed in knp-labs/php-github-api v3.0. Use "Client::AUTH_ACCESS_TOKEN" instead.', E_USER_DEPRECATED); + case Client::AUTH_ACCESS_TOKEN: $request = $request->withHeader('Authorization', sprintf('token %s', $this->tokenOrLogin)); break; case Client::AUTH_URL_CLIENT_ID: + @trigger_error('Using the "Client::AUTH_URL_CLIENT_ID" authentication method is deprecated in knp-labs/php-github-api v2.15 and will be removed in knp-labs/php-github-api v3.0. Use "Client::AUTH_CLIENT_ID" instead.', E_USER_DEPRECATED); + $uri = $request->getUri(); $query = $uri->getQuery(); @@ -61,6 +67,8 @@ public function doHandleRequest(RequestInterface $request, callable $next, calla break; case Client::AUTH_URL_TOKEN: + @trigger_error('Using the "Client::AUTH_URL_TOKEN" authentication method is deprecated in knp-labs/php-github-api v2.15 and will be removed in knp-labs/php-github-api v3.0. Use "Client::AUTH_ACCESS_TOKEN" instead.', E_USER_DEPRECATED); + $uri = $request->getUri(); $query = $uri->getQuery(); @@ -72,11 +80,9 @@ public function doHandleRequest(RequestInterface $request, callable $next, calla $uri = $uri->withQuery($query); $request = $request->withUri($uri); break; - case Client::AUTH_JWT: $request = $request->withHeader('Authorization', sprintf('Bearer %s', $this->tokenOrLogin)); break; - default: throw new RuntimeException(sprintf('%s not yet implemented', $this->method)); break; diff --git a/test/Github/Tests/ClientTest.php b/test/Github/Tests/ClientTest.php index cae5e8f29d1..550bc8169f6 100644 --- a/test/Github/Tests/ClientTest.php +++ b/test/Github/Tests/ClientTest.php @@ -71,7 +71,10 @@ public function getAuthenticationFullData() ['login', 'password', Client::AUTH_HTTP_PASSWORD], ['token', null, Client::AUTH_HTTP_TOKEN], ['token', null, Client::AUTH_URL_TOKEN], + ['token', null, Client::AUTH_ACCESS_TOKEN], ['client_id', 'client_secret', Client::AUTH_URL_CLIENT_ID], + ['client_id', 'client_secret', Client::AUTH_CLIENT_ID], + ['token', null, Client::AUTH_JWT], ]; } diff --git a/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php b/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php new file mode 100644 index 00000000000..bf9f64e1af9 --- /dev/null +++ b/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php @@ -0,0 +1,50 @@ +doHandleRequest($request, static function ($request) use (&$newRequest) { + /** @var Request $newRequest */ + $newRequest = $request; + }, static function () { + throw new \RuntimeException('Did not expect plugin to call first'); + }); + + $this->assertNotNull($newRequest); + + if ($expectedHeader) { + $this->assertContains($expectedHeader, $newRequest->getHeader('Authorization')); + } else { + $this->assertEquals($expectedUrl, $newRequest->getUri()->__toString()); + } + } + + public function getAuthenticationData() + { + return [ + ['login', 'password', Client::AUTH_HTTP_PASSWORD, sprintf('Basic %s', base64_encode('login'.':'.'password'))], + ['access_token', null, Client::AUTH_HTTP_TOKEN, 'token access_token'], + ['token', null, Client::AUTH_URL_TOKEN, null, '/?access_token=token'], + ['access_token', null, Client::AUTH_ACCESS_TOKEN, 'token access_token'], + ['client_id', 'client_secret', Client::AUTH_URL_CLIENT_ID, null, '/?client_id=client_id&client_secret=client_secret'], + ['client_id', 'client_secret', Client::AUTH_CLIENT_ID, sprintf('Basic %s', base64_encode('client_id'.':'.'client_secret'))], + ['jwt_token', null, Client::AUTH_JWT, 'Bearer jwt_token'], + ]; + } +}