Skip to content

Prepare deprecation of authentication methods #870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions doc/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 19 additions & 1 deletion lib/Github/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
10 changes: 8 additions & 2 deletions lib/Github/HttpClient/Plugin/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,23 @@ 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))
);
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();

Expand All @@ -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();

Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions test/Github/Tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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],
];
}

Expand Down
50 changes: 50 additions & 0 deletions test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Github\Tests\HttpClient\Plugin;

use Github\Client;
use Github\HttpClient\Plugin\Authentication;
use GuzzleHttp\Psr7\Request;
use PHPUnit\Framework\TestCase;

class AuthenticationTest extends TestCase
{
/**
* @dataProvider getAuthenticationData
*/
public function testAuthenticationMethods($tokenOrLogin, $password, $method, $expectedHeader = null, $expectedUrl = null)
{
$request = new Request('GET', '/');
$plugin = new Authentication($tokenOrLogin, $password, $method);

/** @var Request $newRequest */
$newRequest = null;
$plugin->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'],
];
}
}