From 04bedaf0cac44fd4b48af84404f509d350975d11 Mon Sep 17 00:00:00 2001 From: iamluc Date: Thu, 29 Dec 2016 10:22:58 +0100 Subject: [PATCH] Allow to set a TokenGenerator to override default implementation. It eases the use of JWT or other token types. --- lib/OAuth2.php | 42 +++++++++++++++++-- lib/TokenGenerator/RandomTokenGenerator.php | 39 +++++++++++++++++ .../TokenGeneratorInterface.php | 14 +++++++ tests/OAuth2Test.php | 22 ++++++++++ .../RandomTokenGeneratorTest.php | 30 +++++++++++++ 5 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 lib/TokenGenerator/RandomTokenGenerator.php create mode 100644 lib/TokenGenerator/TokenGeneratorInterface.php create mode 100644 tests/TokenGenerator/RandomTokenGeneratorTest.php diff --git a/lib/OAuth2.php b/lib/OAuth2.php index 31da279..f02a2f6 100644 --- a/lib/OAuth2.php +++ b/lib/OAuth2.php @@ -5,6 +5,7 @@ use OAuth2\Model\IOAuth2AccessToken; use OAuth2\Model\IOAuth2AuthCode; use OAuth2\Model\IOAuth2Client; +use OAuth2\TokenGenerator\TokenGeneratorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -61,6 +62,13 @@ class OAuth2 */ protected $storage; + /** + * Token Generator (Random, JWT, etc.) + * + * @var TokenGeneratorInterface + */ + private $tokenGenerator; + /** * Keep track of the old refresh token. So we can unset * the old refresh tokens when a new one is issued. @@ -405,6 +413,20 @@ public function __construct(IOAuth2Storage $storage, $config = array()) } } + /** + * Sets a TokenGenerator to override default implementation. + * + * @param TokenGeneratorInterface $tokenGenerator + * + * @return OAuth2 The application (for chained calls of this method) + */ + public function setTokenGenerator(TokenGeneratorInterface $tokenGenerator) + { + $this->tokenGenerator = $tokenGenerator; + + return $this; + } + /** * Default configuration options are specified here. */ @@ -1331,8 +1353,12 @@ private function buildUri($uri, $params) */ public function createAccessToken(IOAuth2Client $client, $data, $scope = null, $access_token_lifetime = null, $issue_refresh_token = true, $refresh_token_lifetime = null) { + $genAccessToken = $this->tokenGenerator + ? $this->tokenGenerator->genAccessToken($client, $data, $scope, $access_token_lifetime, $issue_refresh_token, $refresh_token_lifetime) + : $this->genAccessToken() + ; $token = array( - "access_token" => $this->genAccessToken(), + "access_token" => $genAccessToken, "expires_in" => ($access_token_lifetime ?: $this->getVariable(self::CONFIG_ACCESS_LIFETIME)), "token_type" => $this->getVariable(self::CONFIG_TOKEN_TYPE), "scope" => $scope, @@ -1348,7 +1374,10 @@ public function createAccessToken(IOAuth2Client $client, $data, $scope = null, $ // Issue a refresh token also, if we support them if ($this->storage instanceof IOAuth2RefreshTokens && $issue_refresh_token === true) { - $token["refresh_token"] = $this->genAccessToken(); + $token["refresh_token"] = $this->tokenGenerator + ? $this->tokenGenerator->genRefreshToken($client, $data, $scope, $access_token_lifetime, $issue_refresh_token, $refresh_token_lifetime) + : $this->genAccessToken() + ; $this->storage->createRefreshToken( $token["refresh_token"], $client, @@ -1390,7 +1419,10 @@ public function createAccessToken(IOAuth2Client $client, $data, $scope = null, $ */ private function createAuthCode(IOAuth2Client $client, $data, $redirectUri, $scope = null) { - $code = $this->genAuthCode(); + $code = $this->tokenGenerator + ? $this->tokenGenerator->genAuthCode($client, $data, $scope, $redirectUri) + : $this->genAuthCode() + ; $this->storage->createAuthCode( $code, $client, @@ -1413,6 +1445,8 @@ private function createAuthCode(IOAuth2Client $client, $data, $redirectUri, $sco * * @ingroup oauth2_section_4 * @see OAuth2::genAuthCode() + * + * @deprecated since 1.3, will be removed in 2.0. Use a TokenGenerator instead. */ protected function genAccessToken() { @@ -1446,6 +1480,8 @@ protected function genAccessToken() * @see OAuth2::genAccessToken() * * @ingroup oauth2_section_4 + * + * @deprecated since 1.3, will be removed in 2.0. Use a TokenGenerator instead. */ protected function genAuthCode() { diff --git a/lib/TokenGenerator/RandomTokenGenerator.php b/lib/TokenGenerator/RandomTokenGenerator.php new file mode 100644 index 0000000..11f050f --- /dev/null +++ b/lib/TokenGenerator/RandomTokenGenerator.php @@ -0,0 +1,39 @@ +genAccessToken($client, $data); + } + + public function genAuthCode(IOAuth2Client $client, $data, $scope = null, $redirectUri = null) + { + return $this->genAccessToken($client, $data); + } +} diff --git a/lib/TokenGenerator/TokenGeneratorInterface.php b/lib/TokenGenerator/TokenGeneratorInterface.php new file mode 100644 index 0000000..5cc158f --- /dev/null +++ b/lib/TokenGenerator/TokenGeneratorInterface.php @@ -0,0 +1,14 @@ + OAuth2::GRANT_TYPE_CLIENT_CREDENTIALS, 'client_id' => 'my_little_app', 'client_secret' => 'b') + ); + + $storage = new OAuth2StorageStub; + $storage->addClient(new OAuth2Client('my_little_app', 'b')); + $storage->setAllowedGrantTypes(array(OAuth2::GRANT_TYPE_CLIENT_CREDENTIALS)); + + $tokenGenerator = $this->getMockBuilder('OAuth2\TokenGenerator\TokenGeneratorInterface')->getMock(); + $tokenGenerator->expects($this->once())->method('genAccessToken')->willReturn('aa.bb.cc'); + + $this->fixture = new OAuth2($storage); + $this->fixture->setTokenGenerator($tokenGenerator); + + $response = $this->fixture->grantAccessToken($request); + + // Successful token grant will return a JSON encoded token WITHOUT a refresh token: + $this->assertRegExp('/^{"access_token":"aa\.bb\.cc","expires_in":[^"]+,"token_type":"bearer","scope":null}$/', $response->getContent()); + } + public function getTestGetBearerTokenData() { $data = array(); diff --git a/tests/TokenGenerator/RandomTokenGeneratorTest.php b/tests/TokenGenerator/RandomTokenGeneratorTest.php new file mode 100644 index 0000000..4229c1f --- /dev/null +++ b/tests/TokenGenerator/RandomTokenGeneratorTest.php @@ -0,0 +1,30 @@ +getMockBuilder('OAuth2\Model\IOAuth2Client')->getMock(); + + $this->assertNotEmpty($tokenGenerator->genAccessToken($client, null)); + } + + public function testGenerateRefreshToken() + { + $tokenGenerator = new RandomTokenGenerator(); + $client = $this->getMockBuilder('OAuth2\Model\IOAuth2Client')->getMock(); + + $this->assertNotEmpty($tokenGenerator->genRefreshToken($client, null)); + } + + public function testGenerateAuthCode() + { + $tokenGenerator = new RandomTokenGenerator(); + $client = $this->getMockBuilder('OAuth2\Model\IOAuth2Client')->getMock(); + + $this->assertNotEmpty($tokenGenerator->genAuthCode($client, null)); + } +}