-
Notifications
You must be signed in to change notification settings - Fork 113
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
Allow to set a TokenGenerator to override default implementation. #94
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method should be call the default generator method internally. |
||
*/ | ||
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() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
namespace OAuth2\TokenGenerator; | ||
|
||
use OAuth2\Model\IOAuth2Client; | ||
|
||
class RandomTokenGenerator implements TokenGeneratorInterface | ||
{ | ||
public function genAccessToken(IOAuth2Client $client, $data, $scope = null, $access_token_lifetime = null, $issue_refresh_token = true, $refresh_token_lifetime = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This parameters should be extraced as class members and set over an constructor or setter methods. |
||
{ | ||
if (@file_exists('/dev/urandom')) { // Get 100 bytes of random data | ||
$randomData = file_get_contents('/dev/urandom', false, null, 0, 100); | ||
} elseif (function_exists('openssl_random_pseudo_bytes')) { // Get 100 bytes of pseudo-random data | ||
$bytes = openssl_random_pseudo_bytes(100, $strong); | ||
if (true === $strong && false !== $bytes) { | ||
$randomData = $bytes; | ||
} | ||
} | ||
// Last resort: mt_rand | ||
if (empty($randomData)) { // Get 108 bytes of (pseudo-random, insecure) data | ||
$randomData = mt_rand() . mt_rand() . mt_rand() . uniqid(mt_rand(), true) . microtime(true) . uniqid( | ||
mt_rand(), | ||
true | ||
); | ||
} | ||
|
||
return rtrim(strtr(base64_encode(hash('sha256', $randomData)), '+/', '-_'), '='); | ||
} | ||
|
||
public function genRefreshToken(IOAuth2Client $client, $data, $scope = null, $access_token_lifetime = null, $issue_refresh_token = true, $refresh_token_lifetime = null) | ||
{ | ||
return $this->genAccessToken($client, $data); | ||
} | ||
|
||
public function genAuthCode(IOAuth2Client $client, $data, $scope = null, $redirectUri = null) | ||
{ | ||
return $this->genAccessToken($client, $data); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace OAuth2\TokenGenerator; | ||
|
||
use OAuth2\Model\IOAuth2Client; | ||
|
||
interface TokenGeneratorInterface | ||
{ | ||
public function genAccessToken(IOAuth2Client $client, $data, $scope = null, $access_token_lifetime = null, $issue_refresh_token = true, $refresh_token_lifetime = null); | ||
|
||
public function genRefreshToken(IOAuth2Client $client, $data, $scope = null, $access_token_lifetime = null, $issue_refresh_token = true, $refresh_token_lifetime = null); | ||
|
||
public function genAuthCode(IOAuth2Client $client, $data, $scope = null, $redirectUri = null); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
use OAuth2\TokenGenerator\RandomTokenGenerator; | ||
|
||
class RandomTokenGeneratorTest extends PHPUnit_Framework_TestCase | ||
{ | ||
public function testGenerateAccessToken() | ||
{ | ||
$tokenGenerator = new RandomTokenGenerator(); | ||
$client = $this->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)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DI container should inject the specific generator so the value is set.
If no specific generator is available, then the default generator should be used.