mirror of
https://github.com/elyby/oauth2-server.git
synced 2024-11-02 00:43:11 +05:30
Merge branch 'feature/refresh-token-rotation' into develop
This commit is contained in:
commit
e591fbb25c
@ -54,6 +54,12 @@ class RefreshToken implements GrantTypeInterface {
|
|||||||
*/
|
*/
|
||||||
protected $refreshTokenTTL = 604800;
|
protected $refreshTokenTTL = 604800;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate refresh tokens
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $rotateRefreshTokens = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param Authorization $authServer Authorization server instance
|
* @param Authorization $authServer Authorization server instance
|
||||||
@ -111,6 +117,16 @@ class RefreshToken implements GrantTypeInterface {
|
|||||||
return $this->refreshTokenTTL;
|
return $this->refreshTokenTTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a new access is token, expire the refresh token used and issue a new one.
|
||||||
|
* @param boolean $rotateRefreshTokens Set to true to enable (default = false)
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function rotateRefreshTokens($rotateRefreshTokens = false)
|
||||||
|
{
|
||||||
|
$this->rotateRefreshTokens = $rotateRefreshTokens;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete the refresh token grant
|
* Complete the refresh token grant
|
||||||
* @param null|array $inputParams
|
* @param null|array $inputParams
|
||||||
@ -160,24 +176,32 @@ class RefreshToken implements GrantTypeInterface {
|
|||||||
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
|
||||||
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
$accessTokenExpires = time() + $accessTokenExpiresIn;
|
||||||
|
|
||||||
// Generate a new refresh token
|
|
||||||
$refreshToken = SecureKey::make();
|
|
||||||
$refreshTokenExpires = time() + $this->getRefreshTokenTTL();
|
|
||||||
|
|
||||||
// Revoke the old refresh token
|
|
||||||
$this->authServer->getStorage('session')->removeRefreshToken($authParams['refresh_token']);
|
|
||||||
|
|
||||||
// Associate the new access token with the session
|
// Associate the new access token with the session
|
||||||
$newAccessTokenId = $this->authServer->getStorage('session')->associateAccessToken($accessTokenDetails['session_id'], $accessToken, $accessTokenExpires);
|
$newAccessTokenId = $this->authServer->getStorage('session')->associateAccessToken($accessTokenDetails['session_id'], $accessToken, $accessTokenExpires);
|
||||||
|
|
||||||
// There isn't a request for reduced scopes so assign the original ones
|
if ($this->rotateRefreshTokens === true) {
|
||||||
|
|
||||||
|
// Generate a new refresh token
|
||||||
|
$refreshToken = SecureKey::make();
|
||||||
|
$refreshTokenExpires = time() + $this->getRefreshTokenTTL();
|
||||||
|
|
||||||
|
// Revoke the old refresh token
|
||||||
|
$this->authServer->getStorage('session')->removeRefreshToken($authParams['refresh_token']);
|
||||||
|
|
||||||
|
// Associate the new refresh token with the new access token
|
||||||
|
$this->authServer->getStorage('session')->associateRefreshToken($newAccessTokenId, $refreshToken, $refreshTokenExpires, $authParams['client_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There isn't a request for reduced scopes so assign the original ones (or we're not rotating scopes)
|
||||||
if ( ! isset($authParams['scope'])) {
|
if ( ! isset($authParams['scope'])) {
|
||||||
|
|
||||||
foreach ($scopes as $scope) {
|
foreach ($scopes as $scope) {
|
||||||
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scope['id']);
|
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scope['id']);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
// The request is asking for reduced scopes
|
} elseif ( isset($authParams['scope']) && $this->rotateRefreshTokens === true) {
|
||||||
|
|
||||||
|
// The request is asking for reduced scopes and rotate tokens is enabled
|
||||||
$reqestedScopes = explode($this->authServer->getScopeDelimeter(), $authParams['scope']);
|
$reqestedScopes = explode($this->authServer->getScopeDelimeter(), $authParams['scope']);
|
||||||
|
|
||||||
for ($i = 0; $i < count($reqestedScopes); $i++) {
|
for ($i = 0; $i < count($reqestedScopes); $i++) {
|
||||||
@ -202,16 +226,18 @@ class RefreshToken implements GrantTypeInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Associate the new refresh token with the new access token
|
$response = array(
|
||||||
$this->authServer->getStorage('session')->associateRefreshToken($newAccessTokenId, $refreshToken, $refreshTokenExpires, $authParams['client_id']);
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'access_token' => $accessToken,
|
'access_token' => $accessToken,
|
||||||
'refresh_token' => $refreshToken,
|
|
||||||
'token_type' => 'bearer',
|
'token_type' => 'bearer',
|
||||||
'expires' => $accessTokenExpires,
|
'expires' => $accessTokenExpires,
|
||||||
'expires_in' => $accessTokenExpiresIn
|
'expires_in' => $accessTokenExpiresIn
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($this->rotateRefreshTokens === true) {
|
||||||
|
$response['refresh_token'] = $refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,6 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertArrayHasKey('token_type', $v);
|
$this->assertArrayHasKey('token_type', $v);
|
||||||
$this->assertArrayHasKey('expires', $v);
|
$this->assertArrayHasKey('expires', $v);
|
||||||
$this->assertArrayHasKey('expires_in', $v);
|
$this->assertArrayHasKey('expires_in', $v);
|
||||||
$this->assertArrayHasKey('refresh_token', $v);
|
|
||||||
|
|
||||||
$this->assertEquals($a->getAccessTokenTTL(), $v['expires_in']);
|
$this->assertEquals($a->getAccessTokenTTL(), $v['expires_in']);
|
||||||
$this->assertEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
|
$this->assertEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
|
||||||
@ -240,6 +239,48 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
|
|||||||
'refresh_token' => 'abcdef',
|
'refresh_token' => 'abcdef',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('access_token', $v);
|
||||||
|
$this->assertArrayHasKey('token_type', $v);
|
||||||
|
$this->assertArrayHasKey('expires', $v);
|
||||||
|
$this->assertArrayHasKey('expires_in', $v);
|
||||||
|
|
||||||
|
$this->assertEquals($a->getAccessTokenTTL(), $v['expires_in']);
|
||||||
|
$this->assertEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_issueAccessToken_refreshTokenGrant_rotateTokens()
|
||||||
|
{
|
||||||
|
$this->client->shouldReceive('getClient')->andReturn(array(
|
||||||
|
'client_id' => 1234,
|
||||||
|
'client_secret' => 5678,
|
||||||
|
'redirect_uri' => 'http://foo/redirect',
|
||||||
|
'name' => 'Example Client'
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->session->shouldReceive('validateRefreshToken')->andReturn(1);
|
||||||
|
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
|
||||||
|
$this->session->shouldReceive('updateSession')->andReturn(null);
|
||||||
|
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
|
||||||
|
$this->session->shouldReceive('getAccessToken')->andReturn(null);
|
||||||
|
$this->session->shouldReceive('getScopes')->andReturn(array('id' => 1));
|
||||||
|
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
|
||||||
|
$this->session->shouldReceive('associateRefreshToken')->andReturn(1);
|
||||||
|
$this->session->shouldReceive('removeRefreshToken')->andReturn(1);
|
||||||
|
$this->session->shouldReceive('associateScope')->andReturn(null);
|
||||||
|
|
||||||
|
$a = $this->returnDefault();
|
||||||
|
|
||||||
|
$rt = new League\OAuth2\Server\Grant\RefreshToken($a);
|
||||||
|
$rt->rotateRefreshTokens(true);
|
||||||
|
$a->addGrantType($rt);
|
||||||
|
|
||||||
|
$v = $a->issueAccessToken(array(
|
||||||
|
'grant_type' => 'refresh_token',
|
||||||
|
'client_id' => 1234,
|
||||||
|
'client_secret' => 5678,
|
||||||
|
'refresh_token' => 'abcdef',
|
||||||
|
));
|
||||||
|
|
||||||
$this->assertArrayHasKey('access_token', $v);
|
$this->assertArrayHasKey('access_token', $v);
|
||||||
$this->assertArrayHasKey('token_type', $v);
|
$this->assertArrayHasKey('token_type', $v);
|
||||||
$this->assertArrayHasKey('expires', $v);
|
$this->assertArrayHasKey('expires', $v);
|
||||||
@ -286,7 +327,6 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertArrayHasKey('token_type', $v);
|
$this->assertArrayHasKey('token_type', $v);
|
||||||
$this->assertArrayHasKey('expires', $v);
|
$this->assertArrayHasKey('expires', $v);
|
||||||
$this->assertArrayHasKey('expires_in', $v);
|
$this->assertArrayHasKey('expires_in', $v);
|
||||||
$this->assertArrayHasKey('refresh_token', $v);
|
|
||||||
|
|
||||||
$this->assertNotEquals($a->getAccessTokenTTL(), $v['expires_in']);
|
$this->assertNotEquals($a->getAccessTokenTTL(), $v['expires_in']);
|
||||||
$this->assertNotEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
|
$this->assertNotEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
|
||||||
@ -318,6 +358,7 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
|
|||||||
$a = $this->returnDefault();
|
$a = $this->returnDefault();
|
||||||
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
|
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
|
||||||
$grant->setAccessTokenTTL(30);
|
$grant->setAccessTokenTTL(30);
|
||||||
|
$grant->rotateRefreshTokens(true);
|
||||||
$a->addGrantType($grant);
|
$a->addGrantType($grant);
|
||||||
|
|
||||||
$v = $a->issueAccessToken(array(
|
$v = $a->issueAccessToken(array(
|
||||||
@ -368,6 +409,7 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
|
|||||||
$a = $this->returnDefault();
|
$a = $this->returnDefault();
|
||||||
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
|
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
|
||||||
$grant->setAccessTokenTTL(30);
|
$grant->setAccessTokenTTL(30);
|
||||||
|
$grant->rotateRefreshTokens(true);
|
||||||
$a->addGrantType($grant);
|
$a->addGrantType($grant);
|
||||||
|
|
||||||
$a->issueAccessToken(array(
|
$a->issueAccessToken(array(
|
||||||
|
Loading…
Reference in New Issue
Block a user