Skip to content

Commit

Permalink
Use PSR7 interfaces internally in auth plugins.
Browse files Browse the repository at this point in the history
Use PSR7 methods in the auth plugins. I've changed the return value for
authentication adapters such that they can return a modified request.
The test case using the CompatAuth stub ensure that the current behavior
continues to work as well for backwards compatibility reasons.
  • Loading branch information
markstory committed May 17, 2016
1 parent 38d3cc5 commit 01f016a
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 36 deletions.
14 changes: 8 additions & 6 deletions src/Http/Client.php
Expand Up @@ -435,10 +435,10 @@ protected function _createRequest($method, $url, $data, $options)
$request->cookie($options['cookies']);
}
if (isset($options['auth'])) {
$this->_addAuthentication($request, $options);
$request = $this->_addAuthentication($request, $options);
}
if (isset($options['proxy'])) {
$this->_addProxy($request, $options);
$request = $this->_addProxy($request, $options);
}
return $request;
}
Expand Down Expand Up @@ -480,13 +480,14 @@ protected function _typeHeaders($type)
*
* @param \Cake\Http\Client\Request $request The request to modify.
* @param array $options Array of options containing the 'auth' key.
* @return void
* @return \Cake\Http\Client\Request The updated request object.
*/
protected function _addAuthentication(Request $request, $options)
{
$auth = $options['auth'];
$adapter = $this->_createAuth($auth, $options);
$adapter->authentication($request, $options['auth']);
$result = $adapter->authentication($request, $options['auth']);
return $result ?: $request;
}

/**
Expand All @@ -497,13 +498,14 @@ protected function _addAuthentication(Request $request, $options)
*
* @param \Cake\Http\Client\Request $request The request to modify.
* @param array $options Array of options containing the 'proxy' key.
* @return void
* @return \Cake\Http\Client\Request The updated request object.
*/
protected function _addProxy(Request $request, $options)
{
$auth = $options['proxy'];
$adapter = $this->_createAuth($auth, $options);
$adapter->proxyAuthentication($request, $options['proxy']);
$result = $adapter->proxyAuthentication($request, $options['proxy']);
return $result ?: $request;
}

/**
Expand Down
10 changes: 6 additions & 4 deletions src/Http/Client/Auth/Basic.php
Expand Up @@ -29,31 +29,33 @@ class Basic
*
* @param \Cake\Network\Http\Request $request Request instance.
* @param array $credentials Credentials.
* @return void
* @return \Cake\Network\Http\Request The updated request.
* @see http://www.ietf.org/rfc/rfc2617.txt
*/
public function authentication(Request $request, array $credentials)
{
if (isset($credentials['username'], $credentials['password'])) {
$value = $this->_generateHeader($credentials['username'], $credentials['password']);
$request->header('Authorization', $value);
$request = $request->withHeader('Authorization', $value);
}
return $request;
}

/**
* Proxy Authentication
*
* @param \Cake\Network\Http\Request $request Request instance.
* @param array $credentials Credentials.
* @return void
* @return \Cake\Network\Http\Request The updated request.
* @see http://www.ietf.org/rfc/rfc2617.txt
*/
public function proxyAuthentication(Request $request, array $credentials)
{
if (isset($credentials['username'], $credentials['password'])) {
$value = $this->_generateHeader($credentials['username'], $credentials['password']);
$request->header('Proxy-Authorization', $value);
$request = $request->withHeader('Proxy-Authorization', $value);
}
return $request;
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/Http/Client/Auth/Digest.php
Expand Up @@ -48,22 +48,22 @@ public function __construct(Client $client, $options = null)
*
* @param \Cake\Network\Http\Request $request The request object.
* @param array $credentials Authentication credentials.
* @return void
* @return \Cake\Network\Http\Request The updated request.
* @see http://www.ietf.org/rfc/rfc2617.txt
*/
public function authentication(Request $request, array $credentials)
{
if (!isset($credentials['username'], $credentials['password'])) {
return;
return $request;
}
if (!isset($credentials['realm'])) {
$credentials = $this->_getServerInfo($request, $credentials);
}
if (!isset($credentials['realm'])) {
return;
return $request;
}
$value = $this->_generateHeader($request, $credentials);
$request->header('Authorization', $value);
return $request->withHeader('Authorization', $value);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Http/Client/Auth/Oauth.php
Expand Up @@ -34,7 +34,7 @@ class Oauth
*
* @param \Cake\Network\Http\Request $request The request object.
* @param array $credentials Authentication credentials.
* @return void
* @return \Cake\Network\Http\Request The updated request.
* @throws \Cake\Core\Exception\Exception On invalid signature types.
*/
public function authentication(Request $request, array $credentials)
Expand All @@ -46,7 +46,7 @@ public function authentication(Request $request, array $credentials)
$credentials['tokenSecret']
);
if (!$hasKeys) {
return;
return $request;
}
if (empty($credentials['method'])) {
$credentials['method'] = 'hmac-sha1';
Expand All @@ -64,7 +64,7 @@ public function authentication(Request $request, array $credentials)
default:
throw new Exception(sprintf('Unknown Oauth signature method %s', $credentials['method']));
}
$request->header('Authorization', $value);
return $request->withHeader('Authorization', $value);
}

/**
Expand Down
24 changes: 9 additions & 15 deletions tests/TestCase/Network/Http/Auth/DigestTest.php
Expand Up @@ -57,12 +57,10 @@ public function testRealmAndNonceFromExtraRequest()
->will($this->returnValue($response));

$auth = ['username' => 'admin', 'password' => '1234'];
$request = (new Request())->method(Request::METHOD_GET)
->url('http://example.com/some/path');
$request = new Request('http://example.com/some/path', Request::METHOD_GET);
$request = $this->auth->authentication($request, $auth);

$this->auth->authentication($request, $auth);

$result = $request->header('Authorization');
$result = $request->getHeaderLine('Authorization');
$this->assertContains('Digest', $result);
$this->assertContains('realm="The batcave"', $result);
$this->assertContains('nonce="4cded326c6c51"', $result);
Expand All @@ -89,11 +87,9 @@ public function testQop()
->will($this->returnValue($response));

$auth = ['username' => 'admin', 'password' => '1234'];
$request = (new Request())->method(Request::METHOD_GET)
->url('http://example.com/some/path');

$this->auth->authentication($request, $auth);
$result = $request->header('Authorization');
$request = new Request('http://example.com/some/path', Request::METHOD_GET);
$request = $this->auth->authentication($request, $auth);
$result = $request->getHeaderLine('Authorization');

$this->assertContains('qop="auth"', $result);
$this->assertContains('nc=00000001', $result);
Expand All @@ -117,11 +113,9 @@ public function testOpaque()
->will($this->returnValue($response));

$auth = ['username' => 'admin', 'password' => '1234'];
$request = (new Request())->method(Request::METHOD_GET)
->url('http://example.com/some/path');

$this->auth->authentication($request, $auth);
$result = $request->header('Authorization');
$request = new Request('http://example.com/some/path', Request::METHOD_GET);
$request = $this->auth->authentication($request, $auth);
$result = $request->getHeaderLine('Authorization');

$this->assertContains('opaque="d8ea7aa61a1693024c4cc3a516f49b3c"', $result);
}
Expand Down
8 changes: 4 additions & 4 deletions tests/TestCase/Network/Http/Auth/OauthTest.php
Expand Up @@ -56,9 +56,9 @@ public function testPlainTextSigning()
'method' => 'plaintext',
];
$request = new Request();
$auth->authentication($request, $creds);
$request = $auth->authentication($request, $creds);

$result = $request->header('Authorization');
$result = $request->getHeaderLine('Authorization');
$this->assertContains('OAuth', $result);
$this->assertContains('oauth_version="1.0"', $result);
$this->assertContains('oauth_token="a%20token%20value"', $result);
Expand Down Expand Up @@ -204,9 +204,9 @@ public function testHmacSigning()
'timestamp' => '1191242096'
];
$auth = new Oauth();
$auth->authentication($request, $options);
$request = $auth->authentication($request, $options);

$result = $request->header('Authorization');
$result = $request->getHeaderLine('Authorization');
$expected = 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=';
$this->assertContains(
'oauth_signature="' . $expected . '"',
Expand Down
37 changes: 37 additions & 0 deletions tests/TestCase/Network/Http/ClientTest.php
Expand Up @@ -13,6 +13,7 @@
*/
namespace Cake\Test\TestCase\Network\Http;

use Cake\Core\Configure;
use Cake\Network\Http\Client;
use Cake\Network\Http\Request;
use Cake\Network\Http\Response;
Expand Down Expand Up @@ -344,6 +345,42 @@ public function testGetWithAuthenticationAndProxy()
$this->assertSame($result, $response);
}

/**
* Test authentication adapter that mutates request.
*
* @return void
*/
public function testAuthenticationWithMutation()
{
Configure::write('App.namespace', 'TestApp');
$response = new Response();
$mock = $this->getMock('Cake\Network\Http\Adapter\Stream', ['send']);
$headers = [
'Authorization' => 'Bearer abc123',
'Proxy-Authorization' => 'Bearer abc123',
];
$mock->expects($this->once())
->method('send')
->with($this->callback(function ($request) use ($headers) {
$this->assertEquals(Request::METHOD_GET, $request->getMethod());
$this->assertEquals('http://cakephp.org/', '' . $request->getUri());
$this->assertEquals($headers['Authorization'], $request->getHeaderLine('Authorization'));
$this->assertEquals($headers['Proxy-Authorization'], $request->getHeaderLine('Proxy-Authorization'));
return true;
}))
->will($this->returnValue([$response]));

$http = new Client([
'host' => 'cakephp.org',
'adapter' => $mock
]);
$result = $http->get('/', [], [
'auth' => ['type' => 'TestApp\Http\CompatAuth'],
'proxy' => ['type' => 'TestApp\Http\CompatAuth'],
]);
$this->assertSame($result, $response);
}

/**
* Return a list of HTTP methods.
*
Expand Down
51 changes: 51 additions & 0 deletions tests/test_app/TestApp/Http/CompatAuth.php
@@ -0,0 +1,51 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.3.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace TestApp\Http;

use Cake\Network\Http\Request;

/**
* Testing stub to ensure that auth providers
* that mutate requests in place continue to work.
*
* @deprecated 3.3.0 Remove this compatibility behavior in 4.0.0
*/
class CompatAuth
{

/**
* Add Authorization header to the request via in-place mutation methods.
*
* @param \Cake\Network\Http\Request $request Request instance.
* @param array $credentials Credentials.
* @return \Cake\Network\Http\Request The updated request.
*/
public function authentication(Request $request, array $credentials)
{
$request->header('Authorization', 'Bearer abc123');
}

/**
* Proxy Authentication added via in-place mutation methods.
*
* @param \Cake\Network\Http\Request $request Request instance.
* @param array $credentials Credentials.
* @return \Cake\Network\Http\Request The updated request.
*/
public function proxyAuthentication(Request $request, array $credentials)
{
$request->header('Proxy-Authorization', 'Bearer abc123');
}

}

0 comments on commit 01f016a

Please sign in to comment.