From d88e01c7dd45848bc41ec91d2dc2afa41b428a36 Mon Sep 17 00:00:00 2001 From: Jerry Saravia Date: Thu, 3 Sep 2015 22:50:35 -0400 Subject: [PATCH 1/2] Making client secret optional during refresh and access token requsets. --- src/Grant/AuthCodeGrant.php | 33 ++++++++++++++++++++++++++++++-- src/Grant/RefreshTokenGrant.php | 34 +++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index c0af6b75..943a3b5d 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -60,6 +60,14 @@ class AuthCodeGrant extends AbstractGrant */ protected $authTokenTTL = 600; + /** + * Whether to require the client secret when + * completing the flow. + * + * @var boolean + */ + protected $requireClientSecret = true; + /** * Override the default access token expire time * @@ -72,6 +80,27 @@ class AuthCodeGrant extends AbstractGrant $this->authTokenTTL = $authTokenTTL; } + /** + * + * @param bool $required True to require client secret during access + * token request. False if not. Default = true + */ + public function setRequireClientSecret($required) + { + $this->requireClientSecret = $required; + } + + /** + * True if client secret is required during + * access token request. False if it isn't. + * + * @return bool + */ + public function shouldRequireClientSecret() + { + return $this->requireClientSecret; + } + /** * Check authorize parameters * @@ -184,7 +213,7 @@ class AuthCodeGrant extends AbstractGrant $clientSecret = $this->server->getRequest()->request->get('client_secret', $this->server->getRequest()->getPassword()); - if (is_null($clientSecret)) { + if ($this->shouldRequireClientSecret() && is_null($clientSecret)) { throw new Exception\InvalidRequestException('client_secret'); } @@ -271,4 +300,4 @@ class AuthCodeGrant extends AbstractGrant return $this->server->getTokenType()->generateResponse(); } -} +} \ No newline at end of file diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php index 3357ed5d..d7fd8815 100644 --- a/src/Grant/RefreshTokenGrant.php +++ b/src/Grant/RefreshTokenGrant.php @@ -42,6 +42,14 @@ class RefreshTokenGrant extends AbstractGrant */ protected $refreshTokenRotate = true; + /** + * Whether to require the client secret when + * completing the flow. + * + * @var boolean + */ + protected $requireClientSecret = true; + /** * Set the TTL of the refresh token * @@ -83,6 +91,28 @@ class RefreshTokenGrant extends AbstractGrant return $this->refreshTokenRotate; } + /** + * + * @param bool $required True to require client secret during access + * token request. False if not. Default = true + */ + public function setRequireClientSecret($required) + { + $this->requireClientSecret = $required; + } + + /** + * True if client secret is required during + * access token request. False if it isn't. + * + * @return bool + */ + public function shouldRequireClientSecret() + { + return $this->requireClientSecret; + } + + /** * {@inheritdoc} */ @@ -95,7 +125,7 @@ class RefreshTokenGrant extends AbstractGrant $clientSecret = $this->server->getRequest()->request->get('client_secret', $this->server->getRequest()->getPassword()); - if (is_null($clientSecret)) { + if ($this->shouldRequireClientSecret() && is_null($clientSecret)) { throw new Exception\InvalidRequestException('client_secret'); } @@ -190,4 +220,4 @@ class RefreshTokenGrant extends AbstractGrant return $this->server->getTokenType()->generateResponse(); } -} +} \ No newline at end of file From 8f82e8ef86bc1f35b84cbacd9d0b12c5463a7daf Mon Sep 17 00:00:00 2001 From: Jerry Saravia Date: Thu, 3 Sep 2015 23:16:09 -0400 Subject: [PATCH 2/2] Added test for setRequireClientSecret --- tests/unit/Grant/RefreshTokenGrantTest.php | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/unit/Grant/RefreshTokenGrantTest.php b/tests/unit/Grant/RefreshTokenGrantTest.php index bd5ae5ab..f0ed0d7e 100644 --- a/tests/unit/Grant/RefreshTokenGrantTest.php +++ b/tests/unit/Grant/RefreshTokenGrantTest.php @@ -498,4 +498,73 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase $this->assertTrue(array_key_exists('expires_in', $response)); $this->assertEquals($response['refresh_token'], $_POST['refresh_token']); } + + public function testCompleteFlowShouldRequireClientSecret() + { + $_POST = [ + 'grant_type' => 'refresh_token', + 'client_id' => 'testapp', + 'refresh_token' => 'refresh_token', + ]; + + $server = new AuthorizationServer(); + $grant = new RefreshTokenGrant(); + $grant->setRequireClientSecret(false); + + $clientStorage = M::mock('League\OAuth2\Server\Storage\ClientInterface'); + $clientStorage->shouldReceive('setServer'); + $clientStorage->shouldReceive('get')->andReturn( + (new ClientEntity($server))->hydrate(['id' => 'testapp']) + ); + + $sessionStorage = M::mock('League\OAuth2\Server\Storage\SessionInterface'); + $sessionStorage->shouldReceive('setServer'); + $sessionStorage->shouldReceive('getScopes')->shouldReceive('getScopes')->andReturn([]); + $sessionStorage->shouldReceive('associateScope'); + $sessionStorage->shouldReceive('getByAccessToken')->andReturn( + (new SessionEntity($server)) + ); + + $accessTokenStorage = M::mock('League\OAuth2\Server\Storage\AccessTokenInterface'); + $accessTokenStorage->shouldReceive('setServer'); + $accessTokenStorage->shouldReceive('get')->andReturn( + (new AccessTokenEntity($server)) + ); + $accessTokenStorage->shouldReceive('delete'); + $accessTokenStorage->shouldReceive('create'); + $accessTokenStorage->shouldReceive('getScopes')->andReturn([ + (new ScopeEntity($server))->hydrate(['id' => 'foo']), + ]); + $accessTokenStorage->shouldReceive('associateScope'); + + $refreshTokenStorage = M::mock('League\OAuth2\Server\Storage\RefreshTokenInterface'); + $refreshTokenStorage->shouldReceive('setServer'); + $refreshTokenStorage->shouldReceive('associateScope'); + $refreshTokenStorage->shouldReceive('delete'); + $refreshTokenStorage->shouldReceive('create'); + $refreshTokenStorage->shouldReceive('get')->andReturn( + (new RefreshTokenEntity($server))->setId('refresh_token')->setExpireTime(time() + 86400) + ); + + $scopeStorage = M::mock('League\OAuth2\Server\Storage\ScopeInterface'); + $scopeStorage->shouldReceive('setServer'); + $scopeStorage->shouldReceive('get')->andReturn( + (new ScopeEntity($server))->hydrate(['id' => 'foo']) + ); + + $server->setClientStorage($clientStorage); + $server->setScopeStorage($scopeStorage); + $server->setSessionStorage($sessionStorage); + $server->setAccessTokenStorage($accessTokenStorage); + $server->setRefreshTokenStorage($refreshTokenStorage); + + $server->addGrantType($grant); + + $response = $server->issueAccessToken(); + $this->assertTrue(array_key_exists('access_token', $response)); + $this->assertTrue(array_key_exists('refresh_token', $response)); + $this->assertTrue(array_key_exists('token_type', $response)); + $this->assertTrue(array_key_exists('expires_in', $response)); + + } }