Compare commits

...

65 Commits
2.0.4 ... 2.1.3

Author SHA1 Message Date
Alex Bilbie
a9b52ab56a Version bump 2014-05-23 16:29:49 +01:00
freezy
e72179e6b4 Added normalize headers to 2.1 needed by lucadegasperi/oauth2-server-laravel 2014-05-23 16:28:44 +01:00
Phil Sturgeon
67509d1413 Tagged 2.1.2. 2014-05-13 15:08:41 +01:00
Phil Sturgeon
44f51bfc1c Support Authorization header passed as ENV var
Some hosts (at this point I only know of Fortrabbit) require Authorization headers to be passed as an environment variable, which PHP will then shove into . See more: http://fortrabbit.com/docs/essentials/quirks-and-constraints\#authorization-header
2014-05-13 15:07:44 +01:00
Alex Bilbie
98be9ab252 Merge branch 'release/2.1.1' 2013-06-02 13:55:01 +01:00
Alex Bilbie
e0f4ccb775 Updated changelog 2013-06-02 13:54:54 +01:00
Alex Bilbie
dca0898c2f Version bump 2013-06-02 13:54:47 +01:00
Alex Bilbie
7da9e1a9d7 Merge pull request #64 from alexmcroberts/develop
Conditional isValid flag to check for Authorization header only. Fixes #57
2013-06-02 05:46:45 -07:00
Alex McRoberts
a4a8f6e661 This fixes #57. By passing in a conditional flag refering to headersOnly, the library would stil respect RFC6749 Section 7 and RFC6750 Section 2. 2013-05-27 21:27:30 -07:00
Alex Bilbie
a9ecca92fc Fixed broken test 2013-05-27 19:38:07 +01:00
Alex Bilbie
47c24e3181 Corrected array key call. Fixes #63 2013-05-27 20:33:07 +02:00
Alex Bilbie
92b6ce3335 Added default value for final argument in ClientInterface::getClient(). Fixes #56 2013-05-14 09:00:36 +01:00
Alex Bilbie
ee9549287e Updated docblocks 2013-05-14 08:59:53 +01:00
Alex Bilbie
4b3e0bf668 Fixed semantic meaning of requireScopeParam() and requireStateParam() by changing their default value to true 2013-05-10 23:01:54 -07:00
Alex Bilbie
05d4b68586 Optimised regex and re-added trim() following conversation in #52 2013-05-10 23:00:47 -07:00
Alex Bilbie
ec9c39c108 Merge branch 'release/2.1' into develop 2013-05-10 17:59:37 -07:00
Alex Bilbie
5d0b295a82 Merge branch 'release/2.1' 2013-05-10 17:59:29 -07:00
Alex Bilbie
9ec5442f90 Updated changelog 2013-05-10 17:59:08 -07:00
Alex Bilbie
4112913813 Version bump 2013-05-10 17:58:57 -07:00
Alex Bilbie
5eb4227709 Merge branch 'feature/auth-code-scopes' into develop. Fixes #44 2013-05-10 17:42:05 -07:00
Alex Bilbie
f5251a6080 Updated sessions 2013-05-10 17:39:29 -07:00
Alex Bilbie
86fb02d218 Added cascading relationship between oauth_sessions_authcodes and oauth_sessions 2013-05-10 17:32:39 -07:00
Alex Bilbie
ef4a138237 Fixed associateAuthCodeScope() query 2013-05-10 17:29:28 -07:00
Alex Bilbie
d531a37412 Don't add scope IDs 2013-05-10 17:26:23 -07:00
Alex Bilbie
ca599437f6 Added oauth_session_authcode_scopes 2013-05-10 17:24:46 -07:00
Alex Bilbie
252afddbd3 Updated oauth_session_authcodes table. Added id field, remove scope_ids field 2013-05-10 17:24:31 -07:00
Alex Bilbie
c57c4b1b4f Fixed key name 2013-05-10 17:19:53 -07:00
Alex Bilbie
ba2dc90f3b Altered associateScope logic 2013-05-10 17:08:20 -07:00
Alex Bilbie
7373f312da Updated variable name 2013-05-10 17:08:10 -07:00
Alex Bilbie
a01810d8fa Updated validateAuthCode in PDO Session 2013-05-10 17:07:29 -07:00
Alex Bilbie
3ea3eb5ebd Implemented getAuthCodeScopes() in PDO Session 2013-05-10 17:07:06 -07:00
Alex Bilbie
11022e16ef Updated validateAuthCode() in SessionInterface 2013-05-10 17:06:44 -07:00
Alex Bilbie
8d06a7b685 Updated getAuthCodeScopes() in SessionInterface 2013-05-10 17:06:05 -07:00
Alex Bilbie
c66c8092f9 Revert "Return the session_id for validateAuthCode instead of an array"
This reverts commit 51138f8738.
2013-05-10 16:57:39 -07:00
Alex Bilbie
591139f44d Added associateAuthCodeScope to PDO 2013-05-10 16:57:18 -07:00
Alex Bilbie
410ad09b5c Updated PDO associateAuthCode 2013-05-10 16:56:38 -07:00
Alex Bilbie
51138f8738 Return the session_id for validateAuthCode instead of an array 2013-05-10 16:53:52 -07:00
Alex Bilbie
aa8d38108f Associate scopes to auth codes in separate method. Creating an auth code now returns an ID 2013-05-10 16:53:21 -07:00
Alex Bilbie
9372cc85d0 Added getAuthCodeScopes() method 2013-05-10 16:50:34 -07:00
Alex Bilbie
accb80289f Added associateAuthCodeScope() method 2013-05-10 16:50:13 -07:00
Alex Bilbie
e591fbb25c Merge branch 'feature/refresh-token-rotation' into develop 2013-05-10 16:13:22 -07:00
Alex Bilbie
fdb89fb5e4 Updated tests 2013-05-10 16:13:11 -07:00
Alex Bilbie
ce51821043 If rotateRefreshTokens() is true then associate new access tokens 2013-05-10 16:13:06 -07:00
Alex Bilbie
eac33d50b3 Added missing semicolon 2013-05-10 16:12:43 -07:00
Alex Bilbie
2552b73b17 Added rotateRefreshTokens() method 2013-05-10 16:00:40 -07:00
Alex Bilbie
8c4019693b Updated @ziege's patch to overcome awkward access token definition requirement (i.e. access token can have a space in it) and also optimised code. Fixes #52 2013-05-10 12:57:34 -07:00
ziege
b88ef82563 Fixed two probems in access token check
1) The method returned the wrong result in case when the access token itself contained the string "Bearer".

2) When using cURL, the request is sometimes send twice (in my case when the first request returned a 404 error), and the Authorization header of the second request is doubled, so that you get a "Authorization: Bearer XXX, Bearer XXX". This case is checked now. (BTW: Tested with the current PHP version 5.4.15 on Windows.)
2013-05-10 20:00:01 +02:00
Alex Bilbie
3e5b4a1735 Move zetacomponents/database to "suggest" in composer.json. Fixes #51 2013-05-10 10:13:17 -07:00
Alex Bilbie
41a7125370 Accidentally used PHP 5.4 style bracket 2013-05-09 11:48:21 -07:00
Alex Bilbie
c40484abb1 Merge branch 'feature/refresh-token-rewrite' into develop 2013-05-09 11:42:31 -07:00
Alex Bilbie
f4bcfee687 Update associated scopes if requested in refresh access token. Fixes #47 2013-05-09 11:42:28 -07:00
Alex Bilbie
6d8eb9d05e Added removeRefreshToken method to SessionInterface 2013-05-09 11:40:29 -07:00
Alex Bilbie
76f2f6a5e1 Don't delete old sessions when issuing new access tokens using the Password or Client Credential grants. Fixes #32 2013-05-09 10:43:44 -07:00
Alex Bilbie
d677b765b2 Renamed scopes.key to scopes.scope. Updated ScopeInterface and PDO/Scope. Fixes #45 2013-05-09 10:23:41 -07:00
Alex Bilbie
7035792325 Allow for multiple default scopes. Fixes #42 2013-05-09 10:15:36 -07:00
Alex Bilbie
351c2e97ea If scope parameter is required and there are not requested scopes AND there is no default scope set then fail
Should have been included in with previous commit
2013-05-09 10:06:44 -07:00
Alex Bilbie
ddefb2ee16 Set the scope parameter to not be required by default. Fixes #43 2013-05-09 10:02:41 -07:00
Alex Bilbie
c3b41a5e8a Merge branch 'release/2.0.5' into develop 2013-05-09 09:47:33 -07:00
Alex Bilbie
b16c58bfe1 mErge branch 'release/2.0.5' 2013-05-09 09:47:21 -07:00
Alex Bilbie
e6d0a19e8f Version bump 2013-05-09 09:47:11 -07:00
Alex Bilbie
2296d09e92 Changelog update 2013-05-09 09:47:07 -07:00
Alex Bilbie
69af252844 Fixed docblock 2013-05-09 09:45:10 -07:00
Alex Bilbie
d9c598af3c Removed DEFAULT '' that has slipped in 2013-05-09 09:38:08 -07:00
Alex Bilbie
3cb79fc2b5 Fixed oauth_session_token_scopes primary key 2013-05-09 09:31:05 -07:00
Alex Bilbie
39379fe5b6 Merge branch 'release/2.0.4' into develop 2013-05-09 08:01:45 -07:00
23 changed files with 679 additions and 113 deletions

View File

@@ -1,5 +1,29 @@
# Changelog
## 2.1.1 (released 2013-06-02)
* Added conditional `isValid()` flag to check for Authorization header only (thanks @alexmcroberts)
* Fixed semantic meaning of `requireScopeParam()` and `requireStateParam()` by changing their default value to true
* Updated some duff docblocks
* Corrected array key call in Resource.php (Issue #63)
## 2.1 (released 2013-05-10)
* Moved zetacomponents/database to "suggest" in composer.json. If you rely on this feature you now need to include " zetacomponents/database" into "require" key in your own composer.json. (Issue #51)
* New method in Refresh grant called `rotateRefreshTokens()`. Pass in `true` to issue a new refresh token each time an access token is refreshed. This parameter needs to be set to true in order to request reduced scopes with the new access token. (Issue #47)
* Rename `key` column in oauth_scopes table to `scope` as `key` is a reserved SQL word. (Issue #45)
* The `scope` parameter is no longer required by default as per the RFC. (Issue #43)
* You can now set multiple default scopes by passing an array into `setDefaultScope()`. (Issue #42)
* The password and client credentials grants now allow for multiple sessions per user. (Issue #32)
* Scopes associated to authorization codes are not held in their own table (Issue #44)
* Database schema updates.
## 2.0.5 (released 2013-05-09)
* Fixed `oauth_session_token_scopes` table primary key
* Removed `DEFAULT ''` that has slipped into some tables
* Fixed docblock for `SessionInterface::associateRefreshToken()`
## 2.0.4 (released 2013-05-09)
* Renamed primary key in oauth_client_endpoints table

View File

@@ -1,12 +1,11 @@
{
"name": "league/oauth2-server",
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"version": "2.0.4",
"version": "2.1.3",
"homepage": "https://github.com/php-loep/oauth2-server",
"license": "MIT",
"require": {
"php": ">=5.3.0",
"zetacomponents/database": "dev-master"
"php": ">=5.3.0"
},
"require-dev": {
"mockery/mockery": ">=0.7.2"
@@ -43,5 +42,7 @@
"League\\OAuth2\\Server": "src/"
}
},
"suggest": {}
"suggest": {
"zetacomponents/database": "Allows use of the build in PDO storage classes"
}
}

View File

@@ -29,7 +29,7 @@ CREATE TABLE `oauth_sessions` (
CREATE TABLE `oauth_session_access_tokens` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(10) unsigned NOT NULL,
`access_token` char(40) NOT NULL DEFAULT '',
`access_token` char(40) NOT NULL,
`access_token_expires` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u_oaseacto_acto_seid` (`access_token`,`session_id`),
@@ -38,26 +38,27 @@ CREATE TABLE `oauth_session_access_tokens` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_session_authcodes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(10) unsigned NOT NULL,
`auth_code` char(40) NOT NULL DEFAULT '',
`auth_code` char(40) NOT NULL,
`auth_code_expires` int(10) unsigned NOT NULL,
`scope_ids` char(255) DEFAULT NULL,
PRIMARY KEY (`session_id`),
CONSTRAINT `f_oaseau_seid` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
PRIMARY KEY (`id`),
KEY `session_id` (`session_id`),
CONSTRAINT `oauth_session_authcodes_ibfk_1` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_session_redirects` (
`session_id` int(10) unsigned NOT NULL,
`redirect_uri` varchar(255) NOT NULL DEFAULT '',
`redirect_uri` varchar(255) NOT NULL,
PRIMARY KEY (`session_id`),
CONSTRAINT `f_oasere_seid` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_session_refresh_tokens` (
`session_access_token_id` int(10) unsigned NOT NULL,
`refresh_token` char(40) NOT NULL DEFAULT '',
`refresh_token` char(40) NOT NULL,
`refresh_token_expires` int(10) unsigned NOT NULL,
`client_id` char(40) NOT NULL DEFAULT '',
`client_id` char(40) NOT NULL,
PRIMARY KEY (`session_access_token_id`),
KEY `client_id` (`client_id`),
CONSTRAINT `oauth_session_refresh_tokens_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE,
@@ -65,21 +66,30 @@ CREATE TABLE `oauth_session_refresh_tokens` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_scopes` (
`id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`key` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NOT NULL,
`description` VARCHAR(255) DEFAULT NULL,
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`scope` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u_oasc_sc` (`key`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
UNIQUE KEY `u_oasc_sc` (`scope`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_session_token_scopes` (
`session_token_scope_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`session_access_token_id` int(10) unsigned DEFAULT NULL,
`scope_id` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`session_token_scope_id`),
PRIMARY KEY (`id`),
UNIQUE KEY `u_setosc_setoid_scid` (`session_access_token_id`,`scope_id`),
KEY `f_oasetosc_scid` (`scope_id`),
CONSTRAINT `f_oasetosc_scid` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `f_oasetosc_setoid` FOREIGN KEY (`session_access_token_id`) REFERENCES `oauth_session_access_tokens` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_session_authcode_scopes` (
`oauth_session_authcode_id` int(10) unsigned NOT NULL,
`scope_id` smallint(5) unsigned NOT NULL,
KEY `oauth_session_authcode_id` (`oauth_session_authcode_id`),
KEY `scope_id` (`scope_id`),
CONSTRAINT `oauth_session_authcode_scopes_ibfk_2` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`id`) ON DELETE CASCADE,
CONSTRAINT `oauth_session_authcode_scopes_ibfk_1` FOREIGN KEY (`oauth_session_authcode_id`) REFERENCES `oauth_session_authcodes` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@@ -59,11 +59,11 @@ class Authorization
* Require the "scope" parameter to be in checkAuthoriseParams()
* @var boolean
*/
protected $requireScopeParam = true;
protected $requireScopeParam = false;
/**
* Default scope to be used if none is provided and requireScopeParam is false
* @var string
* Default scope(s) to be used if none is provided
* @var string|array
*/
protected $defaultScope = null;
@@ -287,7 +287,7 @@ class Authorization
/**
* Default scope to be used if none is provided and requireScopeParam is false
* @var string
* @var string|array
*/
public function setDefaultScope($default = null)
{
@@ -318,7 +318,7 @@ class Authorization
* @param boolean $require
* @return void
*/
public function requireStateParam($require = false)
public function requireStateParam($require = true)
{
$this->requireStateParam = $require;
}

View File

@@ -152,10 +152,14 @@ class AuthCode implements GrantTypeInterface {
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
}
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
if ($this->authServer->scopeParamRequired() === true && $this->authServer->getDefaultScope() === null && count($scopes) === 0) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
$scopes = array($this->authServer->getDefaultScope());
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope() !== null) {
if (is_array($this->authServer->getDefaultScope())) {
$scopes = $this->authServer->getDefaultScope();
} else {
$scopes = array($this->authServer->getDefaultScope());
}
}
$authParams['scopes'] = array();
@@ -189,13 +193,6 @@ class AuthCode implements GrantTypeInterface {
// Remove any old sessions the user might have
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], $type, $typeId);
// List of scopes IDs
$scopeIds = array();
foreach ($authParams['scopes'] as $scope)
{
$scopeIds[] = $scope['id'];
}
// Create a new session
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], $type, $typeId);
@@ -203,7 +200,12 @@ class AuthCode implements GrantTypeInterface {
$this->authServer->getStorage('session')->associateRedirectUri($sessionId, $authParams['redirect_uri']);
// Associate the auth code
$this->authServer->getStorage('session')->associateAuthCode($sessionId, $authCode, time() + $this->authTokenTTL, implode(',', $scopeIds));
$authCodeId = $this->authServer->getStorage('session')->associateAuthCode($sessionId, $authCode, time() + $this->authTokenTTL);
// Associate the scopes to the auth code
foreach ($authParams['scopes'] as $scope) {
$this->authServer->getStorage('session')->associateAuthCodeScope($authCodeId, $scope['id']);
}
return $authCode;
}
@@ -245,30 +247,30 @@ class AuthCode implements GrantTypeInterface {
}
// Verify the authorization code matches the client_id and the request_uri
$session = $this->authServer->getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']);
$authCodeDetails = $this->authServer->getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']);
if ( ! $session) {
if ( ! $authCodeDetails) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_grant'), 'code'), 9);
}
// A session ID was returned so update it with an access token and remove the authorisation code
// Get any associated scopes
$scopes = $this->authServer->getStorage('session')->getAuthCodeScopes($authCodeDetails['authcode_id']);
// A session ID was returned so update it with an access token and remove the authorisation code
$accessToken = SecureKey::make();
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
$accessTokenExpires = time() + $accessTokenExpiresIn;
// Remove the auth code
$this->authServer->getStorage('session')->removeAuthCode($session['id']);
$this->authServer->getStorage('session')->removeAuthCode($authCodeDetails['session_id']);
// Create an access token
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($session['id'], $accessToken, $accessTokenExpires);
$accessTokenId = $this->authServer->getStorage('session')->associateAccessToken($authCodeDetails['session_id'], $accessToken, $accessTokenExpires);
// Associate scopes with the access token
if ( ! is_null($session['scope_ids'])) {
$scopeIds = explode(',', $session['scope_ids']);
foreach ($scopeIds as $scopeId) {
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scopeId);
if (count($scopes) > 0) {
foreach ($scopes as $scope) {
$this->authServer->getStorage('session')->associateScope($accessTokenId, $scope['scope_id']);
}
}

View File

@@ -122,10 +122,14 @@ class ClientCredentials implements GrantTypeInterface {
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
}
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
if ($this->authServer->scopeParamRequired() === true && $this->authServer->getDefaultScope() === null && count($scopes) === 0) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
$scopes = array($this->authServer->getDefaultScope());
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope() !== null) {
if (is_array($this->authServer->getDefaultScope())) {
$scopes = $this->authServer->getDefaultScope();
} else {
$scopes = array($this->authServer->getDefaultScope());
}
}
$authParams['scopes'] = array();
@@ -145,9 +149,6 @@ class ClientCredentials implements GrantTypeInterface {
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
$accessTokenExpires = time() + $accessTokenExpiresIn;
// Delete any existing sessions just to be sure
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], 'client', $authParams['client_id']);
// Create a new session
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], 'client', $authParams['client_id']);

View File

@@ -166,10 +166,14 @@ class Password implements GrantTypeInterface {
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
}
if ($this->authServer->scopeParamRequired() === true && count($scopes) === 0) {
if ($this->authServer->scopeParamRequired() === true && $this->authServer->getDefaultScope() === null && count($scopes) === 0) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope()) {
$scopes = array($this->authServer->getDefaultScope());
} elseif (count($scopes) === 0 && $this->authServer->getDefaultScope() !== null) {
if (is_array($this->authServer->getDefaultScope())) {
$scopes = $this->authServer->getDefaultScope();
} else {
$scopes = array($this->authServer->getDefaultScope());
}
}
$authParams['scopes'] = array();
@@ -189,9 +193,6 @@ class Password implements GrantTypeInterface {
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
$accessTokenExpires = time() + $accessTokenExpiresIn;
// Delete any existing sessions just to be sure
$this->authServer->getStorage('session')->deleteSession($authParams['client_id'], 'user', $userId);
// Create a new session
$sessionId = $this->authServer->getStorage('session')->createSession($authParams['client_id'], 'user', $userId);

View File

@@ -54,6 +54,12 @@ class RefreshToken implements GrantTypeInterface {
*/
protected $refreshTokenTTL = 604800;
/**
* Rotate refresh tokens
* @var boolean
*/
protected $rotateRefreshTokens = false;
/**
* Constructor
* @param Authorization $authServer Authorization server instance
@@ -111,6 +117,16 @@ class RefreshToken implements GrantTypeInterface {
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
* @param null|array $inputParams
@@ -119,7 +135,7 @@ class RefreshToken implements GrantTypeInterface {
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = $this->authServer->getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams);
$authParams = $this->authServer->getParam(array('client_id', 'client_secret', 'refresh_token', 'scope'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'client_id'), 0);
@@ -159,24 +175,69 @@ class RefreshToken implements GrantTypeInterface {
$accessToken = SecureKey::make();
$accessTokenExpiresIn = ($this->accessTokenTTL !== null) ? $this->accessTokenTTL : $this->authServer->getAccessTokenTTL();
$accessTokenExpires = time() + $accessTokenExpiresIn;
$refreshToken = SecureKey::make();
$refreshTokenExpires = time() + $this->getRefreshTokenTTL();
// Associate the new access token with the session
$newAccessTokenId = $this->authServer->getStorage('session')->associateAccessToken($accessTokenDetails['session_id'], $accessToken, $accessTokenExpires);
foreach ($scopes as $scope) {
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scope['id']);
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']);
}
$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'])) {
return array(
foreach ($scopes as $scope) {
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scope['id']);
}
} 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']);
for ($i = 0; $i < count($reqestedScopes); $i++) {
$reqestedScopes[$i] = trim($reqestedScopes[$i]);
if ($reqestedScopes[$i] === '') unset($reqestedScopes[$i]); // Remove any junk scopes
}
// Check that there aren't any new scopes being included
$existingScopes = array();
foreach ($scopes as $s) {
$existingScopes[] = $s['scope'];
}
foreach ($reqestedScopes as $reqScope) {
if ( ! in_array($reqScope, $existingScopes)) {
throw new Exception\ClientException(sprintf($this->authServer->getExceptionMessage('invalid_request'), 'scope'), 0);
}
// Associate with the new access token
$scopeDetails = $this->authServer->getStorage('scope')->getScope($reqScope, $authParams['client_id'], $this->identifier);
$this->authServer->getStorage('session')->associateScope($newAccessTokenId, $scopeDetails['id']);
}
}
$response = array(
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if ($this->rotateRefreshTokens === true) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@@ -173,16 +173,17 @@ class Resource
/**
* Checks if the access token is valid or not.
*
* @param $headersOnly Limit Access Token to Authorization header only
* @throws Exception\InvalidAccessTokenException Thrown if the presented access token is not valid
* @return bool
*/
public function isValid()
public function isValid($headersOnly = false)
{
$accessToken = $this->determineAccessToken();
$accessToken = $this->determineAccessToken($headersOnly);
$result = $this->storages['session']->validateAccessToken($accessToken);
if ( ! $result) {
if (! $result) {
throw new Exception\InvalidAccessTokenException('Access token is not valid');
}
@@ -194,7 +195,7 @@ class Resource
$sessionScopes = $this->storages['session']->getScopes($this->accessToken);
foreach ($sessionScopes as $scope) {
$this->sessionScopes[] = $scope['key'];
$this->sessionScopes[] = $scope['scope'];
}
return true;
@@ -224,7 +225,7 @@ class Resource
return false;
} elseif (is_array($scopes)) {
foreach ($scopes as $scope) {
if ( ! in_array($scope, $this->sessionScopes)) {
if (! in_array($scope, $this->sessionScopes)) {
return false;
}
}
@@ -237,14 +238,35 @@ class Resource
/**
* Reads in the access token from the headers.
*
* @param $headersOnly Limit Access Token to Authorization header only
* @throws Exception\MissingAccessTokenException Thrown if there is no access token presented
* @return string
*/
protected function determineAccessToken()
protected function determineAccessToken($headersOnly = false)
{
if ($header = $this->getRequest()->header('Authorization')) {
$accessToken = trim(str_replace('Bearer', '', $header));
} else {
// Try to get it directly from a header
if (! $header = $this->getRequest()->header('Authorization')) {
// Failing that try getting it from a server variable
$header = $this->getRequest()->server('HTTP_AUTHORIZATION');
}
// One of them worked
if ($header) {
// Check for special case, because cURL sometimes does an
// internal second request and doubles the authorization header,
// which always resulted in an error.
//
// 1st request: Authorization: Bearer XXX
// 2nd request: Authorization: Bearer XXX, Bearer XXX
if (strpos($header, ',') !== false) {
$headerPart = explode(',', $header);
$accessToken = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $headerPart[0]));
} else {
$accessToken = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header));
}
$accessToken = ($accessToken === 'Bearer') ? '' : $accessToken;
} elseif ($headersOnly === false) {
$method = $this->getRequest()->server('REQUEST_METHOD');
$accessToken = $this->getRequest()->{$method}($this->tokenKey);
}
@@ -255,5 +277,4 @@ class Resource
return $accessToken;
}
}

View File

@@ -50,8 +50,8 @@ interface ClientInterface
* @param string $clientId The client's ID
* @param string $clientSecret The client's secret (default = "null")
* @param string $redirectUri The client's redirect URI (default = "null")
* @param string $grantType The grant type used in the request
* @param string $grantType The grant type used in the request (default = "null")
* @return bool|array Returns false if the validation fails, array on success
*/
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType);
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType = null);
}

View File

@@ -6,7 +6,7 @@ use League\OAuth2\Server\Storage\ClientInterface;
class Client implements ClientInterface
{
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType)
public function getClient($clientId, $clientSecret = null, $redirectUri = null, $grantType = null)
{
$db = \ezcDbInstance::get();

View File

@@ -10,7 +10,7 @@ class Scope implements ScopeInterface
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('SELECT * FROM oauth_scopes WHERE oauth_scopes.key = :scope');
$stmt = $db->prepare('SELECT * FROM oauth_scopes WHERE oauth_scopes.scope = :scope');
$stmt->bindValue(':scope', $scope);
$stmt->execute();
@@ -22,7 +22,7 @@ class Scope implements ScopeInterface
return array(
'id' => $row->id,
'scope' => $row->key,
'scope' => $row->scope,
'name' => $row->name,
'description' => $row->description
);

View File

@@ -70,17 +70,18 @@ class Session implements SessionInterface
$stmt->execute();
}
public function associateAuthCode($sessionId, $authCode, $expireTime, $scopeIds = null)
public function associateAuthCode($sessionId, $authCode, $expireTime)
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires, scope_ids)
VALUE (:sessionId, :authCode, :authCodeExpires, :scopeIds)');
$stmt = $db->prepare('INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires)
VALUE (:sessionId, :authCode, :authCodeExpires)');
$stmt->bindValue(':sessionId', $sessionId);
$stmt->bindValue(':authCode', $authCode);
$stmt->bindValue(':authCodeExpires', $expireTime);
$stmt->bindValue(':scopeIds', $scopeIds);
$stmt->execute();
return $db->lastInsertId();
}
public function removeAuthCode($sessionId)
@@ -96,12 +97,12 @@ class Session implements SessionInterface
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('SELECT oauth_sessions.id, oauth_session_authcodes.scope_ids FROM oauth_sessions JOIN
oauth_session_authcodes ON oauth_session_authcodes.`session_id` = oauth_sessions.id JOIN
oauth_session_redirects ON oauth_session_redirects.`session_id` = oauth_sessions.id WHERE
oauth_sessions.client_id = :clientId AND oauth_session_authcodes.`auth_code` = :authCode AND
`oauth_session_authcodes`.`auth_code_expires` >= :time AND `oauth_session_redirects`.`redirect_uri`
= :redirectUri');
$stmt = $db->prepare('SELECT oauth_sessions.id AS session_id, oauth_session_authcodes.id AS authcode_id
FROM oauth_sessions JOIN oauth_session_authcodes ON oauth_session_authcodes.`session_id`
= oauth_sessions.id JOIN oauth_session_redirects ON oauth_session_redirects.`session_id`
= oauth_sessions.id WHERE oauth_sessions.client_id = :clientId AND oauth_session_authcodes.`auth_code`
= :authCode AND `oauth_session_authcodes`.`auth_code_expires` >= :time AND
`oauth_session_redirects`.`redirect_uri` = :redirectUri');
$stmt->bindValue(':clientId', $clientId);
$stmt->bindValue(':redirectUri', $redirectUri);
$stmt->bindValue(':authCode', $authCode);
@@ -125,6 +126,15 @@ class Session implements SessionInterface
return ($result === false) ? false : (array) $result;
}
public function removeRefreshToken($refreshToken)
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('DELETE FROM `oauth_session_refresh_tokens` WHERE refresh_token = :refreshToken');
$stmt->bindValue(':refreshToken', $refreshToken);
$stmt->execute();
}
public function validateRefreshToken($refreshToken, $clientId)
{
$db = \ezcDbInstance::get();
@@ -151,6 +161,27 @@ class Session implements SessionInterface
return ($result === false) ? false : (array) $result;
}
public function associateAuthCodeScope($authCodeId, $scopeId)
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('INSERT INTO `oauth_session_authcode_scopes` (`oauth_session_authcode_id`, `scope_id`) VALUES (:authCodeId, :scopeId)');
$stmt->bindValue(':authCodeId', $authCodeId);
$stmt->bindValue(':scopeId', $scopeId);
$stmt->execute();
}
public function getAuthCodeScopes($oauthSessionAuthCodeId)
{
$db = \ezcDbInstance::get();
$stmt = $db->prepare('SELECT scope_id FROM `oauth_session_authcode_scopes` WHERE oauth_session_authcode_id = :authCodeId');
$stmt->bindValue(':authCodeId', $oauthSessionAuthCodeId);
$stmt->execute();
return $stmt->fetchAll();
}
public function associateScope($accessTokenId, $scopeId)
{
$db = \ezcDbInstance::get();

View File

@@ -19,7 +19,7 @@ interface ScopeInterface
* Example SQL query:
*
* <code>
* SELECT * FROM oauth_scopes WHERE oauth_scopes.key = :scope
* SELECT * FROM oauth_scopes WHERE scope = :scope
* </code>
*
* Response:
@@ -28,15 +28,15 @@ interface ScopeInterface
* Array
* (
* [id] => (int) The scope's ID
* [key] => (string) The scope itself
* [scope] => (string) The scope itself
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* </code>
*
* @param string $scope The scope
* @param string $clientId The client ID
* @param string $grantType The grant type used in the request
* @param string $clientId The client ID (default = "null")
* @param string $grantType The grant type used in the request (default = "null")
* @return bool|array If the scope doesn't exist return false
*/
public function getScope($scope, $clientId = null, $grantType = null);

View File

@@ -84,8 +84,8 @@ interface SessionInterface
* Example SQL query:
*
* <code>
* oauth_session_refresh_tokens (session_access_token_id, refresh_token, refresh_token_expires)
* VALUE (:accessTokenId, :refreshToken, :expireTime)
* INSERT INTO oauth_session_refresh_tokens (session_access_token_id, refresh_token, refresh_token_expires,
* client_id) VALUE (:accessTokenId, :refreshToken, :expireTime, :clientId)
* </code>
*
* @param int $accessTokenId The access token ID
@@ -102,17 +102,16 @@ interface SessionInterface
* Example SQL query:
*
* <code>
* INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires, scope_ids)
* VALUE (:sessionId, :authCode, :authCodeExpires, :scopeIds)
* INSERT INTO oauth_session_authcodes (session_id, auth_code, auth_code_expires)
* VALUE (:sessionId, :authCode, :authCodeExpires)
* </code>
*
* @param int $sessionId The session ID
* @param string $authCode The authorization code
* @param int $expireTime Unix timestamp of the access token expiry time
* @param string $scopeIds Comma seperated list of scope IDs to be later associated (default = null)
* @return void
* @return int The auth code ID
*/
public function associateAuthCode($sessionId, $authCode, $expireTime, $scopeIds = null);
public function associateAuthCode($sessionId, $authCode, $expireTime);
/**
* Remove an associated authorization token from a session
@@ -134,7 +133,7 @@ interface SessionInterface
* Example SQL query:
*
* <code>
* SELECT oauth_sessions.id, oauth_session_authcodes.scope_ids FROM oauth_sessions
* SELECT oauth_sessions.id AS session_id, oauth_session_authcodes.id AS authcode_id FROM oauth_sessions
* JOIN oauth_session_authcodes ON oauth_session_authcodes.`session_id` = oauth_sessions.id
* JOIN oauth_session_redirects ON oauth_session_redirects.`session_id` = oauth_sessions.id WHERE
* oauth_sessions.client_id = :clientId AND oauth_session_authcodes.`auth_code` = :authCode
@@ -146,8 +145,8 @@ interface SessionInterface
*
* <code>
* array(
* 'id' => (int), // the session ID
* 'scope_ids' => (string)
* 'session_id' => (int)
* 'authcode_id' => (int)
* )
* </code>
*
@@ -185,6 +184,20 @@ interface SessionInterface
*/
public function validateAccessToken($accessToken);
/**
* Removes a refresh token
*
* Example SQL query:
*
* <code>
* DELETE FROM `oauth_session_refresh_tokens` WHERE refresh_token = :refreshToken
* </code>
*
* @param string $refreshToken The refresh token to be removed
* @return void
*/
public function removeRefreshToken($refreshToken);
/**
* Validate a refresh token
*
@@ -226,6 +239,50 @@ interface SessionInterface
*/
public function getAccessToken($accessTokenId);
/**
* Associate scopes with an auth code (bound to the session)
*
* Example SQL query:
*
* <code>
* INSERT INTO `oauth_session_authcode_scopes` (`oauth_session_authcode_id`, `scope_id`) VALUES
* (:authCodeId, :scopeId)
* </code>
*
* @param int $authCodeId The auth code ID
* @param int $scopeId The scope ID
* @return void
*/
public function associateAuthCodeScope($authCodeId, $scopeId);
/**
* Get the scopes associated with an auth code
*
* Example SQL query:
*
* <code>
* SELECT scope_id FROM `oauth_session_authcode_scopes` WHERE oauth_session_authcode_id = :authCodeId
* </code>
*
* Expected response:
*
* <code>
* array(
* array(
* 'scope_id' => (int)
* ),
* array(
* 'scope_id' => (int)
* ),
* ...
* )
* </code>
*
* @param int $oauthSessionAuthCodeId The session ID
* @return array
*/
public function getAuthCodeScopes($oauthSessionAuthCodeId);
/**
* Associate a scope with an access token
*

View File

@@ -39,6 +39,8 @@ class Request implements RequestInterface
if (empty($headers)) {
$this->headers = $this->readHeaders();
} else {
$this->headers = $this->normalizeHeaders($headers);
}
}
@@ -88,8 +90,8 @@ class Request implements RequestInterface
}
}
return $headers;
}
return $this->normalizeHeaders($headers);
}
protected function getPropertyValue($property, $index = null, $default = null)
{
@@ -106,4 +108,39 @@ class Request implements RequestInterface
return $this->{$property}[$index];
}
/**
* Takes all of the headers and normalizes them in a canonical form.
*
* @param array $headers The request headers.
* @return array An arry of headers with the header name normalized
*/
protected function normalizeHeaders(array $headers)
{
$normalized = array();
foreach ($headers as $key => $value) {
$normalized[ucfirst($this->normalizeKey($key))] = $value;
}
return $normalized;
}
/**
* Transform header name into canonical form
*
* Taken from the Slim codebase...
*
* @param string $key
* @return string
*/
protected function normalizeKey($key)
{
$key = strtolower($key);
$key = str_replace(array('-', '_'), ' ', $key);
$key = preg_replace('#^http #', '', $key);
$key = ucwords($key);
$key = str_replace(' ', '-', $key);
return $key;
}
}

View File

@@ -156,6 +156,7 @@ class Auth_Code_Grant_Test extends PHPUnit_Framework_TestCase
$g = new League\OAuth2\Server\Grant\AuthCode($a);
$a->addGrantType($g);
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));
$a->requireScopeParam(true);
$g->checkAuthoriseParams(array(
'client_id' => 1234,
@@ -196,6 +197,41 @@ class Auth_Code_Grant_Test extends PHPUnit_Framework_TestCase
));
$this->assertArrayHasKey('scopes', $params);
$this->assertEquals(1, count($params['scopes']));
}
public function test_checkAuthoriseParams_defaultScopeArray()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->scope->shouldReceive('getScope')->andReturn(array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
));
$a = $this->returnDefault();
$g = new League\OAuth2\Server\Grant\AuthCode($a);
$a->addGrantType($g);
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));
$a->setDefaultScope(array('test.scope', 'test.scope2'));
$a->requireScopeParam(false);
$params = $g->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => ''
));
$this->assertArrayHasKey('scopes', $params);
$this->assertEquals(2, count($params['scopes']));
}
/**
@@ -340,7 +376,8 @@ class Auth_Code_Grant_Test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->session->shouldReceive('associateRedirectUri')->andReturn(null);
$this->session->shouldReceive('associateAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAuthCode')->andReturn(1);
$this->session->shouldReceive('associateAuthCodeScope')->andReturn(null);
$a = $this->returnDefault();
$g = new League\OAuth2\Server\Grant\AuthCode($a);

View File

@@ -358,13 +358,14 @@ class Authorization_Server_test extends PHPUnit_Framework_TestCase
));
$this->session->shouldReceive('validateAuthCode')->andReturn(array(
'id' => 1,
'scope_ids' => '1'
'session_id' => 1,
'authcode_id' => 1
));
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('removeAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->session->shouldReceive('getAuthCodeScopes')->andReturn(array('scope_id' => 1));
$a = $this->returnDefault();
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));
@@ -399,6 +400,8 @@ class Authorization_Server_test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('removeAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('getAuthCodeScopes')->andReturn(array('scope_id' => 1));
$this->session->shouldReceive('associateScope')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));
@@ -436,6 +439,8 @@ class Authorization_Server_test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('removeAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('getAuthCodeScopes')->andReturn(array('scope_id' => 1));
$this->session->shouldReceive('associateScope')->andReturn(null);
$a = $this->returnDefault();
$grant = new League\OAuth2\Server\Grant\AuthCode($a);
@@ -477,6 +482,8 @@ class Authorization_Server_test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('removeAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('getAuthCodeScopes')->andReturn(array('scope_id' => 1));
$this->session->shouldReceive('associateScope')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));

View File

@@ -146,6 +146,47 @@ class Client_Credentials_Grant_Test extends PHPUnit_Framework_TestCase
$this->assertArrayHasKey('expires_in', $v);
}
public function test_issueAccessToken_clientCredentialsGrant_defaultScopeArray()
{
$this->scope->shouldReceive('getScope')->andReturn(array(
'id' => 1,
'key' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
));
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$a = $this->returnDefault();
$a->addGrantType(new League\OAuth2\Server\Grant\ClientCredentials($a));
$a->requireScopeParam(false);
$a->setDefaultScope(array('foobar', 'barfoo'));
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234,
'client_secret' => 5678,
'scope' => ''
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
}
/**
* @expectedException League\OAuth2\Server\Exception\ClientException
* @expectedExceptionCode 4

View File

@@ -338,6 +338,54 @@ class Password_Grant_Test extends PHPUnit_Framework_TestCase
$this->assertArrayHasKey('expires_in', $v);
}
public function test_issueAccessToken_passwordGrant_defaultScopeArray()
{
$this->scope->shouldReceive('getScope')->andReturn(array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
));
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$testCredentials = function() { return 1; };
$a = $this->returnDefault();
$pgrant = new League\OAuth2\Server\Grant\Password($a);
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$a->requireScopeParam(false);
$a->setDefaultScope(array('foobar', 'barfoo'));
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar',
'scope' => ''
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
}
public function test_issueAccessToken_passwordGrant_goodScope()
{
$this->scope->shouldReceive('getScope')->andReturn(array(

View File

@@ -42,6 +42,8 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('removeAuthCode')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('associateRefreshToken')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->session->shouldReceive('getAuthCodeScopes')->andReturn(array('scope_id' => 1));
$a = $this->returnDefault();
$a->addGrantType(new League\OAuth2\Server\Grant\AuthCode($a));
@@ -183,6 +185,7 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('associateRefreshToken')->andReturn(1);
$this->session->shouldReceive('removeRefreshToken')->andReturn(1);
$this->session->shouldReceive('getAccessToken')->andReturn(null);
$this->session->shouldReceive('getScopes')->andReturn(array());
@@ -203,7 +206,6 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a->getAccessTokenTTL(), $v['expires_in']);
$this->assertEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
@@ -226,6 +228,7 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$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();
@@ -238,6 +241,48 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
'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('token_type', $v);
$this->assertArrayHasKey('expires', $v);
@@ -265,6 +310,7 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$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();
@@ -279,6 +325,52 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
'refresh_token' => 'abcdef',
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertNotEquals($a->getAccessTokenTTL(), $v['expires_in']);
$this->assertNotEquals(time()+$a->getAccessTokenTTL(), $v['expires']);
$this->assertEquals(30, $v['expires_in']);
$this->assertEquals(time()+30, $v['expires']);
}
public function test_issueAccessToken_refreshTokenGrant_newScopes()
{
$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(array('id' => 1, 'scope' => 'foo'), array('id' => 2, 'scope' => 'bar')));
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('associateRefreshToken')->andReturn(1);
$this->session->shouldReceive('removeRefreshToken')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->scope->shouldReceive('getScope')->andReturn(array('id' => 1, 'scope' => 'foo'));
$a = $this->returnDefault();
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
$grant->setAccessTokenTTL(30);
$grant->rotateRefreshTokens(true);
$a->addGrantType($grant);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
'refresh_token' => 'abcdef',
'scope' => 'foo'
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
@@ -290,4 +382,44 @@ class Refresh_Token_test extends PHPUnit_Framework_TestCase
$this->assertEquals(30, $v['expires_in']);
$this->assertEquals(time()+30, $v['expires']);
}
/**
* @expectedException League\OAuth2\Server\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_badNewScopes()
{
$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(array('id' => 1, 'scope' => 'foo'), array('id' => 2, 'scope' => 'bar')));
$this->session->shouldReceive('associateAccessToken')->andReturn(1);
$this->session->shouldReceive('associateRefreshToken')->andReturn(1);
$this->session->shouldReceive('removeRefreshToken')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$this->scope->shouldReceive('getScope')->andReturn(array('id' => 1, 'scope' => 'foo'));
$a = $this->returnDefault();
$grant = new League\OAuth2\Server\Grant\RefreshToken($a);
$grant->setAccessTokenTTL(30);
$grant->rotateRefreshTokens(true);
$a->addGrantType($grant);
$a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
'refresh_token' => 'abcdef',
'scope' => 'foobar'
));
}
}

View File

@@ -83,6 +83,24 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase
$method->invoke($s);
}
/**
* @expectedException League\OAuth2\Server\Exception\InvalidAccessTokenException
*/
public function test_determineAccessToken_brokenCurlRequest()
{
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer, Bearer abcdef';
$request = new League\OAuth2\Server\Util\Request(array(), array(), array(), array(), $_SERVER);
$s = $this->returnDefault();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$method->invoke($s);
}
public function test_determineAccessToken_fromHeader()
{
$request = new League\OAuth2\Server\Util\Request();
@@ -106,6 +124,29 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase
$this->assertEquals('abcdef', $result);
}
public function test_determineAccessToken_fromBrokenCurlHeader()
{
$request = new League\OAuth2\Server\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer abcdef, Bearer abcdef'
));
$s = $this->returnDefault();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$result = $method->invoke($s);
$this->assertEquals('abcdef', $result);
}
public function test_determineAccessToken_fromMethod()
{
$s = $this->returnDefault();
@@ -155,8 +196,8 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase
));
$this->session->shouldReceive('getScopes')->andReturn(array(
array('key' => 'foo'),
array('key' => 'bar')
array('scope' => 'foo'),
array('scope' => 'bar')
));
$request = new League\OAuth2\Server\Util\Request();

View File

@@ -59,6 +59,20 @@ class Request_test extends PHPUnit_Framework_TestCase
$this->assertEquals(array('Host' => 'foobar.com'), $this->request->header());
}
function test_canonical_header()
{
$request = new League\OAuth2\Server\Util\Request(
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('HTTP_HOST' => 'foobar.com'),
array('authorization' => 'Bearer ajdfkljadslfjasdlkj')
);
$this->assertEquals('Bearer ajdfkljadslfjasdlkj', $request->header('Authorization'));
}
/**
* @expectedException InvalidArgumentException
*/