Merge branch 'feature/reorg' into develop

This commit is contained in:
Alex Bilbie 2013-02-05 16:27:01 +00:00
commit 7293d47234
52 changed files with 2394 additions and 2533 deletions

View File

@ -4,5 +4,5 @@ php:
- 5.3 - 5.3
- 5.4 - 5.4
before_script: composer install before_script: composer install --dev
script: phpunit -c build/phpunit.xml script: phpunit -c build/phpunit.xml

View File

@ -9,7 +9,7 @@ The framework is provided as a Composer package which can be installed by adding
```javascript ```javascript
{ {
"require": { "require": {
"lncd\Oauth2": "*" "lncd\OAuth2": "*"
} }
} }
``` ```

View File

@ -2,10 +2,13 @@
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="../tests/Bootstrap.php"> <phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="../tests/Bootstrap.php">
<testsuites> <testsuites>
<testsuite name="Authentication Server"> <testsuite name="Authentication Server">
<directory suffix="test.php">../tests/authentication</directory> <directory suffix="Test.php">../tests/authentication</directory>
</testsuite> </testsuite>
<testsuite name="Resource Server"> <testsuite name="Resource Server">
<directory suffix="test.php">../tests/resource</directory> <directory suffix="Test.php">../tests/resource</directory>
</testsuite>
<testsuite name="Utility Methods">
<directory suffix="Test.php">../tests/util</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <filter>
@ -13,7 +16,9 @@
<directory suffix=".php">PEAR_INSTALL_DIR</directory> <directory suffix=".php">PEAR_INSTALL_DIR</directory>
<directory suffix=".php">PHP_LIBDIR</directory> <directory suffix=".php">PHP_LIBDIR</directory>
<directory suffix=".php">../vendor/composer</directory> <directory suffix=".php">../vendor/composer</directory>
<directory suffix=".php">../vendor/mockery</directory>
<directory suffix=".php">../tests</directory> <directory suffix=".php">../tests</directory>
<directory suffix=".php">../testing</directory>
</blacklist> </blacklist>
</filter> </filter>
<logging> <logging>

View File

@ -5,11 +5,11 @@
"homepage": "https://github.com/lncd/OAuth2", "homepage": "https://github.com/lncd/OAuth2",
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": ">=5.3.0", "php": ">=5.3.0"
"guzzle/guzzle": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "*" "phpunit/phpunit": "*",
"mockery/mockery": ">=0.7.2"
}, },
"repositories": [ "repositories": [
{ {
@ -35,10 +35,8 @@
], ],
"autoload": { "autoload": {
"psr-0": { "psr-0": {
"Oauth2": "src/" "OAuth2": "src/"
} }
}, },
"suggest": { "suggest": {}
"lncd/oauth2-facebook": "Adds support for Facebook as an IDP"
}
} }

View File

@ -49,12 +49,10 @@ CREATE TABLE `scopes` (
CREATE TABLE `oauth_session_scopes` ( CREATE TABLE `oauth_session_scopes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(11) unsigned NOT NULL, `session_id` int(11) unsigned NOT NULL,
`access_token` varchar(40) NOT NULL DEFAULT '', `scope_id` int(11) unsigned NOT NULL,
`scope` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `session_id` (`session_id`), KEY `session_id` (`session_id`),
KEY `access_token` (`access_token`), KEY `scope_id` (`scope_id`),
KEY `scope` (`scope`), CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `scopes` (`id`) ON DELETE CASCADE,
CONSTRAINT `oauth_session_scopes_ibfk_3` FOREIGN KEY (`scope`) REFERENCES `scopes` (`scope`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

295
src/OAuth2/AuthServer.php Normal file
View File

@ -0,0 +1,295 @@
<?php
namespace OAuth2;
use OAuth2\Util\Request;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
use OAuth2\Grant\GrantTypeInterface;
class AuthServer
{
/**
* The delimeter between scopes specified in the scope query string parameter
*
* The OAuth 2 specification states it should be a space but that is stupid
* and everyone excepted Google use a comma instead.
*
* @var string
*/
protected $scopeDelimeter = ',';
static protected $expiresIn = 3600;
protected $responseTypes = array();
static protected $storages = array();
static protected $grantTypes = array();
static protected $request = null;
/**
* Exception error codes
* @var array
*/
protected $exceptionCodes = array(
0 => 'invalid_request',
1 => 'unauthorized_client',
2 => 'access_denied',
3 => 'unsupported_response_type',
4 => 'invalid_scope',
5 => 'server_error',
6 => 'temporarily_unavailable',
7 => 'unsupported_grant_type',
8 => 'invalid_client',
9 => 'invalid_grant'
);
/**
* Exception error messages
* @var array
*/
static protected $exceptionMessages = array(
'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
'unauthorized_client' => 'The client is not authorized to request an access token using this method.',
'access_denied' => 'The resource owner or authorization server denied the request.',
'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.',
'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.',
'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.',
'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server',
'invalid_client' => 'Client authentication failed',
'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.',
'invalid_credentials' => 'The user credentials were incorrect.',
'invalid_refresh' => 'The refresh token is invalid.',
);
public static function getExceptionMessage($error = '')
{
return self::$exceptionMessages[$error];
}
public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope)
{
self::$storages = array(
'client' => $client,
'session' => $session,
'scope' => $scope
);
}
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
{
if (is_null($identifier)) {
$identifier = $grantType->getIdentifier();
}
self::$grantTypes[$identifier] = $grantType;
if ( ! is_null($grantType->getResponseType())) {
$this->responseTypes[] = $grantType->getResponseType();
}
}
public static function hasGrantType($identifier)
{
return (array_key_exists($identifier, self::$grantTypes));
}
public function getScopeDelimeter()
{
return $this->scopeDelimeter;
}
public function setScopeDelimeter($scope_delimeter)
{
$this->scopeDelimeter = $scope_delimeter;
}
public static function getExpiresIn()
{
return self::$expiresIn;
}
public function setExpiresIn($expiresIn)
{
self::$expiresIn = $expiresIn;
}
/**
* Sets the Request Object
*
* @param RequestInterface The Request Object
*/
public function setRequest(Util\RequestInterface $request)
{
self::$request = $request;
}
/**
* Gets the Request object. It will create one from the globals if one is not set.
*
* @return RequestInterface
*/
public static function getRequest()
{
if (self::$request === null) {
// @codeCoverageIgnoreStart
self::$request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return self::$request;
}
public static function getStorage($obj)
{
return self::$storages[$obj];
}
/**
* Check authorise parameters
*
* @access public
* @param array $inputParams Optional array of parsed $_GET keys
* @return array Authorise request parameters
*/
public function checkAuthoriseParams($inputParams = array())
{
$authParams = array();
// Client ID
$authParams['client_id'] = (isset($inputParams['client_id'])) ?
$inputParams['client_id'] :
self::getRequest()->get('client_id');
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'client_id'), 0);
}
// Redirect URI
$authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ?
$inputParams['redirect_uri'] :
self::getRequest()->get('redirect_uri');
if (is_null($authParams['redirect_uri'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'redirect_uri'), 0);
}
// Validate client ID and redirect URI
$clientDetails = self::getStorage('client')->getClient($authParams['client_id'], null, $authParams['redirect_uri']);
if ($clientDetails === false) {
throw new Exception\ClientException(self::$exceptionMessages['invalid_client'], 8);
}
$authParams['client_details'] = $clientDetails;
// Response type
$authParams['response_type'] = (isset($inputParams['response_type'])) ?
$inputParams['response_type'] :
self::getRequest()->get('response_type');
if (is_null($authParams['response_type'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'response_type'), 0);
}
// Ensure response type is one that is recognised
if ( ! in_array($authParams['response_type'], $this->responseTypes)) {
throw new Exception\ClientException(self::$exceptionMessages['unsupported_response_type'], 3);
}
// Get and validate scopes
$scopes = (isset($inputParams['scope'])) ?
$inputParams['scope'] :
self::getRequest()->get('scope', '');
$scopes = explode($this->scopeDelimeter, $scopes);
for ($i = 0; $i < count($scopes); $i++) {
$scopes[$i] = trim($scopes[$i]);
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
}
if (count($scopes) === 0) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'scope'), 0);
}
$authParams['scopes'] = array();
foreach ($scopes as $scope) {
$scopeDetails = self::getStorage('scope')->getScope($scope);
if ($scopeDetails === false) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_scope'], $scope), 4);
}
$authParams['scopes'][] = $scopeDetails;
}
return $authParams;
}
/**
* Parse a new authorise request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authoriseParams The authorise request $_GET parameters
* @return string An authorisation code
*/
public function newAuthoriseRequest($type, $typeId, $authParams = array())
{
// Generate an auth code
$authCode = SecureKey::make();
// Remove any old sessions the user might have
self::getStorage('session')->deleteSession($authParams['client_id'], $type, $typeId);
// Create a new session
$sessionId = self::getStorage('session')->createSession($authParams['client_id'], $authParams['redirect_uri'], $type, $typeId, $authCode);
// Associate scopes with the new session
foreach ($authParams['scopes'] as $scope)
{
self::getStorage('session')->associateScope($sessionId, $scope['id']);
}
return $authCode;
}
/**
* Issue an access token
*
* @access public
* @param array $inputParams Optional array of parsed $_POST keys
* @return array Authorise request parameters
*/
public function issueAccessToken($inputParams = array())
{
$authParams['grant_type'] = (isset($inputParams['grant_type'])) ?
$inputParams['grant_type'] :
self::getRequest()->post('grant_type');
if (is_null($authParams['grant_type'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0);
}
// Ensure grant type is one that is recognised and is enabled
if ( ! in_array($authParams['grant_type'], array_keys(self::$grantTypes))) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $authParams['grant_type']), 7);
}
// Complete the flow
return $this->getGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams);
}
protected function getGrantType($grantType)
{
return self::$grantTypes[$grantType];
}
}

View File

@ -100,9 +100,9 @@ abstract class IDP {
abstract public function urlAccessToken(); abstract public function urlAccessToken();
abstract public function urlUserDetails(\Oauth2\Client\Token\Access $token); abstract public function urlUserDetails(\OAuth2\Client\Token\Access $token);
abstract public function userDetails($response, \Oauth2\Client\Token\Access $token); abstract public function userDetails($response, \OAuth2\Client\Token\Access $token);
public function authorize($options = array()) public function authorize($options = array())
{ {
@ -191,24 +191,24 @@ abstract class IDP {
if (isset($result['error']) && ! empty($result['error'])) { if (isset($result['error']) && ! empty($result['error'])) {
throw new \Oauth2\Client\IDPException($result); throw new \OAuth2\Client\IDPException($result);
} }
switch ($params['grant_type']) { switch ($params['grant_type']) {
case 'authorization_code': case 'authorization_code':
return \Oauth2\Client\Token::factory('access', $result); return \OAuth2\Client\Token::factory('access', $result);
break; break;
case 'refresh_token': case 'refresh_token':
return \Oauth2\Client\Token::factory('refresh', $result); return \OAuth2\Client\Token::factory('refresh', $result);
break; break;
} }
} }
public function getUserDetails(\Oauth2\Client\Token\Access $token) public function getUserDetails(\OAuth2\Client\Token\Access $token)
{ {
$url = $this->urlUserDetails($token); $url = $this->urlUserDetails($token);
@ -223,7 +223,7 @@ abstract class IDP {
catch (\Guzzle\Http\Exception\BadResponseException $e) catch (\Guzzle\Http\Exception\BadResponseException $e)
{ {
$raw_response = explode("\n", $e->getResponse()); $raw_response = explode("\n", $e->getResponse());
throw new \Oauth2\Client\IDPException(end($raw_response)); throw new \OAuth2\Client\IDPException(end($raw_response));
} }
} }

View File

@ -1,6 +1,6 @@
<?php <?php
class Blooie extends Oauth2\Client\IDP class Blooie extends OAuth2\Client\IDP
{ {
public $scope = array('user.profile', 'user.picture'); public $scope = array('user.profile', 'user.picture');
@ -16,7 +16,7 @@ class Blooie extends Oauth2\Client\IDP
return 'https://bloo.ie/oauth/access_token'; return 'https://bloo.ie/oauth/access_token';
} }
public function getUserInfo(Oauth2\Token\Access $token) public function getUserInfo(OAuth2\Token\Access $token)
{ {
$url = 'https://graph.facebook.com/me?'.http_build_query(array( $url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token, 'access_token' => $token->access_token,

View File

@ -9,7 +9,7 @@
* @license http://philsturgeon.co.uk/code/dbad-license * @license http://philsturgeon.co.uk/code/dbad-license
*/ */
class Facebook extends Oauth2\Client\IDP class Facebook extends OAuth2\Client\IDP
{ {
protected $scope = array('offline_access', 'email', 'read_stream'); protected $scope = array('offline_access', 'email', 'read_stream');
@ -23,7 +23,7 @@ class Facebook extends Oauth2\Client\IDP
return 'https://graph.facebook.com/oauth/access_token'; return 'https://graph.facebook.com/oauth/access_token';
} }
public function getUserInfo(Oauth2\Token\Access $token) public function getUserInfo(OAuth2\Token\Access $token)
{ {
$url = 'https://graph.facebook.com/me?'.http_build_query(array( $url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token, 'access_token' => $token->access_token,

View File

@ -9,7 +9,7 @@
* @license http://philsturgeon.co.uk/code/dbad-license * @license http://philsturgeon.co.uk/code/dbad-license
*/ */
class Foursquare extends Oauth2\Client\IDP class Foursquare extends OAuth2\Client\IDP
{ {
public $method = 'POST'; public $method = 'POST';
@ -23,7 +23,7 @@ class Foursquare extends Oauth2\Client\IDP
return 'https://foursquare.com/oauth2/access_token'; return 'https://foursquare.com/oauth2/access_token';
} }
public function getUserInfo(Oauth2\Token\Access $token) public function getUserInfo(OAuth2\Token\Access $token)
{ {
$url = 'https://api.foursquare.com/v2/users/self?'.http_build_query(array( $url = 'https://api.foursquare.com/v2/users/self?'.http_build_query(array(
'oauth_token' => $token->access_token, 'oauth_token' => $token->access_token,

View File

@ -9,7 +9,7 @@
* @license http://philsturgeon.co.uk/code/dbad-license * @license http://philsturgeon.co.uk/code/dbad-license
*/ */
class OAuth2_Provider_Github extends Oauth2\Client\IDP class OAuth2_Provider_Github extends OAuth2\Client\IDP
{ {
public function urlAuthorize() public function urlAuthorize()
{ {

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Oauth2\Client; namespace OAuth2\Client;
abstract class Token abstract class Token
{ {
@ -16,7 +16,7 @@ abstract class Token
{ {
include_once 'Token/'.ucfirst(strtolower($name)).'.php'; include_once 'Token/'.ucfirst(strtolower($name)).'.php';
$class = 'Oauth2\Client\Token\\'.ucfirst($name); $class = 'OAuth2\Client\Token\\'.ucfirst($name);
return new $class($options); return new $class($options);
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Oauth2\Client\Token; namespace OAuth2\Client\Token;
/** /**
* OAuth2 Token * OAuth2 Token
@ -11,7 +11,7 @@ namespace Oauth2\Client\Token;
* @copyright (c) 2011 HappyNinjas Ltd * @copyright (c) 2011 HappyNinjas Ltd
*/ */
class Access extends \Oauth2\Client\Token class Access extends \OAuth2\Client\Token
{ {
/** /**
* @var string accessToken * @var string accessToken

View File

@ -8,7 +8,7 @@
* @copyright (c) 2011 HappyNinjas Ltd * @copyright (c) 2011 HappyNinjas Ltd
*/ */
class Authorize extends \Oauth2\Client\Token class Authorize extends \OAuth2\Client\Token
{ {
/** /**
* @var string code * @var string code

View File

@ -0,0 +1,8 @@
<?php
namespace OAuth2\Exception;
class ClientException extends OAuth2Exception
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace OAuth2\Exception;
class InvalidGrantTypeException extends OAuth2Exception
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace OAuth2\Exception;
class MissingAccessTokenException extends OAuth2Exception
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace OAuth2\Exception;
class OAuth2Exception extends \Exception
{
}

View File

@ -0,0 +1,114 @@
<?php
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
class AuthCode implements GrantTypeInterface {
protected $identifier = 'authorization_code';
protected $responseType = 'code';
public function getIdentifier()
{
return $this->identifier;
}
public function getResponseType()
{
return $this->responseType;
}
public function completeFlow($inputParams = null, $authParams = array())
{
// Client ID
$authParams['client_id'] = (isset($inputParams['client_id'])) ?
$inputParams['client_id'] :
AuthServer::getRequest()->post('client_id');
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
// Client secret
$authParams['client_secret'] = (isset($inputParams['client_secret'])) ?
$inputParams['client_secret'] :
AuthServer::getRequest()->post('client_secret');
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Redirect URI
$authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ?
$inputParams['redirect_uri'] :
AuthServer::getRequest()->post('redirect_uri');
if (is_null($authParams['redirect_uri'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'redirect_uri'), 0);
}
// Validate client ID and redirect URI
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
// The authorization code
$authParams['code'] = (isset($inputParams['code'])) ?
$inputParams['code'] :
AuthServer::getRequest()->post('code');
if (is_null($authParams['code'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'code'), 0);
}
// Verify the authorization code matches the client_id and the request_uri
$session = AuthServer::getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']);
if ( ! $session) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_grant'), 'code'), 9);
}
// A session ID was returned so update it with an access token,
// remove the authorisation code, change the stage to 'granted'
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
AuthServer::getStorage('session')->updateSession(
$session['id'],
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if (AuthServer::hasGrantType('refresh_token')) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
class ClientCredentials implements GrantTypeInterface {
protected $identifier = 'client_credentials';
protected $responseType = null;
public function getIdentifier()
{
return $this->identifier;
}
public function getResponseType()
{
return $this->responseType;
}
public function completeFlow($inputParams = null, $authParams = array())
{
// Client ID
$authParams['client_id'] = (isset($inputParams['client_id'])) ?
$inputParams['client_id'] :
AuthServer::getRequest()->post('client_id');
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
// Client secret
$authParams['client_secret'] = (isset($inputParams['client_secret'])) ?
$inputParams['client_secret'] :
AuthServer::getRequest()->post('client_secret');
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and redirect URI
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
// Generate an access token
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
// Delete any existing sessions just to be sure
AuthServer::getStorage('session')->deleteSession($authParams['client_id'], 'client', $authParams['client_id']);
// Create a new session
AuthServer::getStorage('session')->createSession(
$authParams['client_id'],
null,
'client',
$authParams['client_id'],
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if (AuthServer::hasGrantType('refresh_token')) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
interface GrantTypeInterface
{
/**
* Returns the grant identifier (used to validate grant_type in OAuth2\AuthServer\issueAccessToken())
* @return string
*/
public function getIdentifier();
/**
* Returns the response type (used to validate response_type in OAuth2\AuthServer\checkAuthoriseParams())
* @return null|string
*/
public function getResponseType();
/**
* Complete the grant flow
*
* Example response:
* <code>
* array(
* 'access_token' => (string), // The access token
* 'refresh_token' => (string), // The refresh token (only set if the refresh token grant is enabled)
* 'token_type' => 'bearer', // Almost always "bearer" (exceptions: JWT, SAML)
* 'expires' => (int), // The timestamp of when the access token will expire
* 'expires_in' => (int) // The number of seconds before the access token will expire
* )
* </code>
*
* @param null|array $inputParams Null unless the input parameters have been manually set
* @param array $authParams The authorisation paramaters that have been set so far in the request
* @return array An array of parameters to be passed back to the client
*/
public function completeFlow($inputParams = null, $authParams = array());
}

View File

@ -0,0 +1,94 @@
<?php
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
class RefreshToken implements GrantTypeInterface {
protected $identifier = 'refresh_token';
protected $responseType = null;
public function getIdentifier()
{
return $this->identifier;
}
public function getResponseType()
{
return $this->responseType;
}
public function completeFlow($inputParams = null, $authParams = array())
{
// Client ID
$authParams['client_id'] = (isset($inputParams['client_id'])) ?
$inputParams['client_id'] :
AuthServer::getRequest()->post('client_id');
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
// Client secret
$authParams['client_secret'] = (isset($inputParams['client_secret'])) ?
$inputParams['client_secret'] :
AuthServer::getRequest()->post('client_secret');
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and redirect URI
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
// Refresh token
$authParams['refresh_token'] = (isset($inputParams['refresh_token'])) ?
$inputParams['refresh_token'] :
AuthServer::getRequest()->post('refresh_token');
if (is_null($authParams['refresh_token'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'refresh_token'), 0);
}
// Validate refresh token
$sessionId = AuthServer::getStorage('client')->validateRefreshToken(
$authParams['refresh_token'],
$authParams['client_id']
);
if ($sessionId === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_refresh'), 0);
}
// Generate new tokens
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
AuthServer::getStorage('session')->updateRefreshToken($sessionId, $accessToken, $refreshToken, $accessTokenExpires);
return array(
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
}
}

View File

@ -0,0 +1,176 @@
<?php
namespace OAuth2;
use OutOfBoundsException;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\SessionScopeInterface;
use OAuth2\Util\RequestInterface;
class ResourceServer
{
protected $accessToken = null;
protected $sessionId = null;
protected $ownerType = null;
protected $ownerId = null;
protected $sessionScopes = array();
protected $storages = array();
protected $request = null;
protected $tokenKey = 'oauth_token';
/**
* Sets up the Resource
*
* @param SessionInterface The Session Storage Object
* @param SessionScopeInterface The Session Scope Storage Object
*/
public function __construct(SessionInterface $session)
{
$this->storages['session'] = $session;
}
/**
* Sets the Request Object
*
* @param RequestInterface The Request Object
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;
}
/**
* Gets the Request object. It will create one from the globals if one is not set.
*
* @return RequestInterface
*/
public function getRequest()
{
if ($this->request === null) {
// @codeCoverageIgnoreStart
$this->request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return $this->request;
}
public function getTokenKey()
{
return $this->tokenKey;
}
public function setTokenKey($key)
{
$this->tokenKey = $key;
}
/**
* Gets the Owner ID.
*
* @return int
*/
public function getOwnerId()
{
return $this->ownerId;
}
/**
* Gets the Owner Type.
*
* @return string
*/
public function getOwnerType()
{
return $this->ownerType;
}
/**
* Gets the Access Token.
*
* @return string
*/
public function getAccessToken()
{
return $this->accessToken;
}
/**
* Checks if the Access Token is valid or not.
*
* @return bool
*/
public function isValid()
{
$access_token = $this->determineAccessToken();
$result = $this->storages['session']->validateAccessToken($access_token);
if ( ! $result) {
return false;
}
$this->accessToken = $access_token;
$this->sessionId = $result['id'];
$this->ownerType = $result['owner_type'];
$this->ownerId = $result['owner_id'];
$this->sessionScopes = $this->storages['session']->getScopes($this->sessionId);
return true;
}
/**
* Checks if the current session has the given scope(s).
*
* @param array
*/
public function hasScope($scopes)
{
if (is_string($scopes)) {
if (in_array($scopes, $this->sessionScopes)) {
return true;
}
return false;
} elseif (is_array($scopes)) {
foreach ($scopes as $scope) {
if ( ! in_array($scope, $this->sessionScopes)) {
return false;
}
}
return true;
}
return false;
}
/**
* Reads in the Access Token from the headers.
*
* @return string
* @throws Exception\MissingAccessTokenException
*/
protected function determineAccessToken()
{
if ($header = $this->getRequest()->header('Authorization')) {
$access_token = trim(str_replace('Bearer', '', $header));
} else {
$method = $this->getRequest()->server('REQUEST_METHOD');
$access_token = $this->getRequest()->{$method}($this->tokenKey);
}
if (empty($access_token)) {
throw new Exception\MissingAccessTokenException('Access Token is Missing');
}
return $access_token;
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace OAuth2\Storage;
interface ClientInterface
{
/**
* Validate a client
*
* Example SQL query:
*
* <code>
* # Client ID + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* client_endpoints.redirect_uri = $redirectUri
*
* # Client ID + client secret
* SELECT clients.id FROM clients WHERE clients.id = $clientId AND
* clients.secret = $clientSecret
*
* # Client ID + client secret + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* clients.secret = $clientSecret AND client_endpoints.redirect_uri =
* $redirectUri
* </code>
*
* Response:
*
* <code>
* Array
* (
* [client_id] => (string) The client ID
* [client secret] => (string) The client secret
* [redirect_uri] => (string) The redirect URI used in this request
* [name] => (string) The name of the client
* )
* </code>
*
* @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")
* @return bool|array Returns false if the validation fails, array on success
*/
public function getClient($clientId = null, $clientSecret = null, $redirectUri = null);
}

View File

@ -0,0 +1,32 @@
<?php
namespace OAuth2\Storage;
interface ScopeInterface
{
/**
* Return information about a scope
*
* Example SQL query:
*
* <code>
* SELECT * FROM scopes WHERE scope = $scope
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The scope's ID
* [scope] => (string) The scope itself
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* </code>
*
* @param string $scope The scope
* @return bool|array If the scope doesn't exist return false
*/
public function getScope($scope);
}

View File

@ -1,58 +1,13 @@
<?php <?php
namespace Oauth2\Authentication; namespace OAuth2\Storage;
interface Database interface SessionInterface
{ {
/** /**
* Validate a client
*
* Database query:
*
* <code>
* # Client ID + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* client_endpoints.redirect_uri = $redirectUri
*
* # Client ID + client secret
* SELECT clients.id FROM clients WHERE clients.id = $clientId AND
* clients.secret = $clientSecret
*
* # Client ID + client secret + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* clients.secret = $clientSecret AND client_endpoints.redirect_uri =
* $redirectUri
* </code>
*
* Response:
*
* <code>
* Array
* (
* [client_id] => (string) The client ID
* [client secret] => (string) The client secret
* [redirect_uri] => (string) The redirect URI used in this request
* [name] => (string) The name of the client
* )
* </code>
*
* @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")
* @return bool|array Returns false if the validation fails, array on success
*/
public function validateClient(
$clientId,
$clientSecret = null,
$redirectUri = null
);
/**
* Create a new OAuth session * Create a new OAuth session
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type, * INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type,
@ -71,7 +26,7 @@ interface Database
* @param string $stage The stage of the session (default ="request") * @param string $stage The stage of the session (default ="request")
* @return int The session ID * @return int The session ID
*/ */
public function newSession( public function createSession(
$clientId, $clientId,
$redirectUri, $redirectUri,
$type = 'user', $type = 'user',
@ -86,7 +41,7 @@ interface Database
/** /**
* Update an OAuth session * Update an OAuth session
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* UPDATE oauth_sessions SET auth_code = $authCode, access_token = * UPDATE oauth_sessions SET auth_code = $authCode, access_token =
@ -129,31 +84,32 @@ interface Database
$typeId $typeId
); );
public function validateRefreshToken($refreshToken, $clientId);
/** /**
* Update the refresh token * Return the session ID for a given session owner and client combination
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token = * SELECT id FROM oauth_sessions WHERE client_id = $clientId
* $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE * AND owner_type = $type AND owner_id = $typeId
* id = $sessionId
* </code> * </code>
* *
* @param string $sessionId The session ID * @param string $type The session owner's type
* @param string $newAccessToken The new access token for this session * @param string $typeId The session owner's ID
* @param string $newRefreshToken The new refresh token for the session * @param string $clientId The client ID
* @param int $accessTokenExpires The UNIX timestamp of when the new token expires * @return string|null Return the session ID as an integer if
* @return void * found otherwise returns false
*/ */
public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires); public function sessionExists(
$type,
$typeId,
$clientId
);
/** /**
* Validate that an authorisation code is valid * Validate that an authorisation code is valid
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientID AND * SELECT id FROM oauth_sessions WHERE client_id = $clientID AND
@ -191,47 +147,10 @@ interface Database
$authCode $authCode
); );
/**
* Return the session ID for a given session owner and client combination
*
* Database query:
*
* <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientId
* AND owner_type = $type AND owner_id = $typeId
* </code>
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param string $clientId The client ID
* @return string|null Return the session ID as an integer if
* found otherwise returns false
*/
public function hasSession(
$type,
$typeId,
$clientId
);
/**
* Return the access token for a given session
*
* Database query:
*
* <code>
* SELECT access_token FROM oauth_sessions WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return string|null Returns the access token as a string if
* found otherwise returns null
*/
public function getAccessToken($sessionId);
/** /**
* Removes an authorisation code associated with a session * Removes an authorisation code associated with a session
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId * UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId
@ -245,7 +164,7 @@ interface Database
/** /**
* Sets a sessions access token * Sets a sessions access token
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* UPDATE oauth_sessions SET access_token = $accessToken WHERE id = * UPDATE oauth_sessions SET access_token = $accessToken WHERE id =
@ -261,74 +180,64 @@ interface Database
$accessToken $accessToken
); );
public function validateAccessToken($accessToken);
/**
* Return the access token for a given session
*
* Example SQL query:
*
* <code>
* SELECT access_token FROM oauth_sessions WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return string|null Returns the access token as a string if
* found otherwise returns null
*/
public function getAccessToken($sessionId);
public function validateRefreshToken($refreshToken, $clientId);
/**
* Update the refresh token
*
* Example SQL query:
*
* <code>
* UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token =
* $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE
* id = $sessionId
* </code>
*
* @param string $sessionId The session ID
* @param string $newAccessToken The new access token for this session
* @param string $newRefreshToken The new refresh token for the session
* @param int $accessTokenExpires The UNIX timestamp of when the new token expires
* @return void
*/
public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires);
/** /**
* Associates a session with a scope * Associates a session with a scope
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* INSERT INTO oauth_session_scopes (session_id, scope) VALUE ($sessionId, * INSERT INTO oauth_session_scopes (session_id, scope_id) VALUE ($sessionId,
* $scope) * $scopeId)
* </code> * </code>
* *
* @param int $sessionId The session ID * @param int $sessionId The session ID
* @param string $scope The scope * @param string $scope The scope ID
* @return void * @return void
*/ */
public function addSessionScope( public function associateScope($sessionId, $scopeId);
$sessionId,
$scope
);
/**
* Return information about a scope
*
* Database query:
*
* <code>
* SELECT * FROM scopes WHERE scope = $scope
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The scope's ID
* [scope] => (string) The scope itself
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* </code>
*
* @param string $scope The scope
* @return array
*/
public function getScope($scope);
/**
* Associate a session's scopes with an access token
*
* Database query:
*
* <code>
* UPDATE oauth_session_scopes SET access_token = $accessToken WHERE
* session_id = $sessionId
* </code>
*
* @param int $sessionId The session ID
* @param string $accessToken The access token
* @return void
*/
public function updateSessionScopeAccessToken(
$sessionId,
$accessToken
);
/** /**
* Return the scopes associated with an access token * Return the scopes associated with an access token
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* SELECT scopes.scope, scopes.name, scopes.description FROM * SELECT scopes.scope, scopes.name, scopes.description FROM
@ -353,5 +262,5 @@ interface Database
* @param string $accessToken The access token * @param string $accessToken The access token
* @return array * @return array
*/ */
public function accessTokenScopes($accessToken); public function getScopes($accessToken);
} }

View File

@ -0,0 +1,12 @@
<?php
namespace OAuth2\Util;
class RedirectUri
{
public static function make($uri, $params = array(), $queryDelimeter = '?')
{
$uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&';
return $uri.http_build_query($params);
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace OAuth2\Util;
use OutOfBoundsException;
use InvalidMethodCallException;
use InvalidArgumentException;
class Request implements RequestInterface
{
protected $get = array();
protected $post = array();
protected $cookies = array();
protected $files = array();
protected $server = array();
protected $headers = array();
public static function buildFromGlobals()
{
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
}
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array())
{
$this->get = $get;
$this->post = $post;
$this->cookies = $cookies;
$this->files = $files;
$this->server = $server;
if (empty($headers)) {
$this->headers = $this->readHeaders();
}
}
public function get($index = null, $default = null)
{
return $this->getPropertyValue('get', $index, $default);
}
public function post($index = null, $default = null)
{
return $this->getPropertyValue('post', $index, $default);
}
public function file($index = null, $default = null)
{
return $this->getPropertyValue('files', $index, $default);
}
public function cookie($index = null, $default = null)
{
return $this->getPropertyValue('cookies', $index, $default);
}
public function server($index = null, $default = null)
{
return $this->getPropertyValue('server', $index, $default);
}
public function header($index = null, $default = null)
{
return $this->getPropertyValue('headers', $index, $default);
}
protected function readHeaders()
{
$headers = array();
foreach ($this->server() as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$headers[$name] = $value;
}
}
return $headers;
}
protected function getPropertyValue($property, $index = null, $default = null)
{
if ( ! isset($this->{$property})) {
throw new InvalidArgumentException("Property '$property' does not exist.");
}
if (is_null($index)) {
return $this->{$property};
}
if ( ! array_key_exists($index, $this->{$property})) {
return $default;
}
return $this->{$property}[$index];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace OAuth2\Util;
interface RequestInterface
{
public static function buildFromGlobals();
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array());
public function get($index = null);
public function post($index = null);
public function cookie($index = null);
public function file($index = null);
public function server($index = null);
public function header($index = null);
}

View File

@ -0,0 +1,23 @@
<?php
namespace OAuth2\Util;
class SecureKey
{
public static function make($len = 40)
{
// We generate twice as many bytes here because we want to ensure we have
// enough after we base64 encode it to get the length we need because we
// take out the "/", "+", and "=" characters.
$bytes = openssl_random_pseudo_bytes($len * 2, $strong);
// We want to stop execution if the key fails because, well, that is bad.
if ($bytes === false || $strong === false) {
// @codeCoverageIgnoreStart
throw new \Exception('Error Generating Key');
// @codeCoverageIgnoreEnd
}
return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len);
}
}

View File

@ -1,791 +0,0 @@
<?php
namespace Oauth2\Authentication;
class ClientException extends \Exception
{
}
class UserException extends \Exception
{
}
class ServerException extends \Exception
{
}
class Server
{
/**
* Reference to the database abstractor
* @var object
*/
private $_db = null;
/**
* Server configuration
* @var array
*/
private $_config = array(
'scope_delimeter' => ',',
'access_token_ttl' => 3600
);
/**
* Supported response types
* @var array
*/
private $_responseTypes = array(
'code'
);
/**
* Supported grant types
* @var array
*/
private $_grantTypes = array(
'authorization_code' => false,
'client_credentials' => false,
'password' => false,
'refresh_token' => false,
);
private $_grantTypeCallbacks = array(
'password' => null
);
/**
* Exception error codes
* @var array
*/
public $exceptionCodes = array(
0 => 'invalid_request',
1 => 'unauthorized_client',
2 => 'access_denied',
3 => 'unsupported_response_type',
4 => 'invalid_scope',
5 => 'server_error',
6 => 'temporarily_unavailable',
7 => 'unsupported_grant_type',
8 => 'invalid_client',
9 => 'invalid_grant'
);
/**
* Error codes.
*
* To provide i8ln errors just overwrite the keys
*
* @var array
*/
public $errors = array(
'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
'unauthorized_client' => 'The client is not authorized to request an access token using this method.',
'access_denied' => 'The resource owner or authorization server denied the request.',
'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.',
'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.',
'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.',
'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server',
'invalid_client' => 'Client authentication failed',
'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.',
'invalid_credentials' => 'The user credentials were incorrect.',
'invalid_refresh' => 'The refresh token is invalid.',
);
/**
* Constructor
*
* @access public
* @param array $options Optional list of options to overwrite the defaults
* @return void
*/
public function __construct($options = null)
{
if ($options !== null) {
$this->_config = array_merge($this->_config, $options);
}
}
/**
* Register a database abstrator class
*
* @access public
* @param object $db A class that implements OAuth2ServerDatabase
* @return void
*/
public function registerDbAbstractor($db)
{
$this->_db = $db;
}
/**
* Enable a grant type
*
* @access public
* @return void
*/
public function enableGrantType($type, $callback = null)
{
if (isset($this->_grantTypes[$type])) {
$this->_grantTypes[$type] = true;
}
if (in_array($type, array_keys($this->_grantTypeCallbacks))) {
if (is_null($callback) || ! is_callable($callback)) {
throw new ServerException('No registered callback function for grant type `'.$type.'`');
}
$this->_grantTypeCallbacks[$type] = $callback;
}
}
/**
* Check client authorise parameters
*
* @access public
* @param array $authParams Optional array of parsed $_GET keys
* @return array Authorise request parameters
*/
public function checkClientAuthoriseParams($authParams = null)
{
$params = array();
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_GET['client_id'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
}
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_GET['client_id'];
// Redirect URI
if ( ! isset($authParams['redirect_uri']) && ! isset($_GET['redirect_uri'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0);
}
$params['redirect_uri'] = (isset($authParams['redirect_uri'])) ?
$authParams['redirect_uri'] :
$_GET['redirect_uri'];
// Validate client ID and redirect URI
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
null,
$params['redirect_uri']
);
if ($clientDetails === false) {
throw new ClientException($this->errors['invalid_client'], 8);
}
$params['client_details'] = $clientDetails;
// Response type
if ( ! isset($authParams['response_type']) && ! isset($_GET['response_type'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'response_type'), 0);
}
$params['response_type'] = (isset($authParams['response_type'])) ?
$authParams['response_type'] :
$_GET['response_type'];
// Ensure response type is one that is recognised
if ( ! in_array($params['response_type'], $this->_responseTypes)) {
throw new ClientException($this->errors['unsupported_response_type'], 3);
}
// Get and validate scopes
if (isset($authParams['scope']) || isset($_GET['scope'])) {
$scopes = (isset($_GET['scope'])) ?
$_GET['scope'] :
$authParams['scope'];
$scopes = explode($this->_config['scope_delimeter'], $scopes);
// Remove any junk scopes
for ($i = 0; $i < count($scopes); $i++) {
$scopes[$i] = trim($scopes[$i]);
if ($scopes[$i] === '') {
unset($scopes[$i]);
}
}
if (count($scopes) === 0) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'scope'), 0);
}
$params['scopes'] = array();
foreach ($scopes as $scope) {
$scopeDetails = $this->_dbCall(
'getScope',
$scope
);
if ($scopeDetails === false) {
throw new ClientException(sprintf($this->errors['invalid_scope'], $scope), 4);
}
$params['scopes'][] = $scopeDetails;
}
}
return $params;
}
/**
* Parse a new authorise request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authoriseParams The authorise request $_GET parameters
* @return string An authorisation code
*/
public function newAuthoriseRequest($type, $typeId, $authoriseParams)
{
// Remove any old sessions the user might have
$this->_dbCall(
'deleteSession',
$authoriseParams['client_id'],
$type,
$typeId
);
// Create the new auth code
$authCode = $this->_newAuthCode(
$authoriseParams['client_id'],
'user',
$typeId,
$authoriseParams['redirect_uri'],
$authoriseParams['scopes']
);
return $authCode;
}
/**
* Generate a unique code
*
* Generate a unique code for an authorisation code, or token
*
* @return string A unique code
*/
private function _generateCode()
{
return sha1(uniqid(microtime()));
}
/**
* Create a new authorisation code
*
* @param string $clientId The client ID
* @param string $type The type of the owner of the session
* @param string $typeId The session owner's ID
* @param string $redirectUri The redirect URI
* @param array $scopes The requested scopes
* @param string $accessToken The access token (default = null)
* @return string An authorisation code
*/
private function _newAuthCode($clientId, $type, $typeId, $redirectUri, $scopes = array())
{
$authCode = $this->_generateCode();
// Delete any existing sessions just to be sure
$this->_dbCall('deleteSession', $clientId, $type, $typeId);
// Create a new session
$sessionId = $this->_dbCall(
'newSession',
$clientId,
$redirectUri,
$type,
$typeId,
$authCode,
null,
null,
'requested'
);
// Add the scopes
foreach ($scopes as $key => $scope) {
$this->_dbCall(
'addSessionScope',
$sessionId,
$scope['scope']
);
}
return $authCode;
}
/**
* Issue an access token
*
* @access public
*
* @param array $authParams Optional array of parsed $_POST keys
*
* @return array Authorise request parameters
*/
public function issueAccessToken($authParams = null)
{
if ( ! isset($authParams['grant_type']) && ! isset($_POST['grant_type'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'grant_type'), 0);
}
$params['grant_type'] = (isset($authParams['grant_type'])) ?
$authParams['grant_type'] :
$_POST['grant_type'];
// Ensure grant type is one that is recognised and is enabled
if ( ! in_array($params['grant_type'], array_keys($this->_grantTypes)) || $this->_grantTypes[$params['grant_type']] !== true) {
throw new ClientException(sprintf($this->errors['unsupported_grant_type'], $params['grant_type']), 7);
}
switch ($params['grant_type'])
{
case 'authorization_code': // Authorization code grant
return $this->_completeAuthCodeGrant($authParams, $params);
break;
case 'client_credentials': // Client credentials grant
return $this->_completeClientCredentialsGrant($authParams, $params);
break;
case 'password': // Resource owner password credentials grant
return $this->_completeUserCredentialsGrant($authParams, $params);
break;
case 'refresh_token': // Refresh token grant
return $this->_completeRefreshTokenGrant($authParams, $params);
break;
// @codeCoverageIgnoreStart
default: // Unsupported
throw new ServerException($this->errors['server_error'] . 'Tried to process an unsuppported grant type.', 5);
break;
}
// @codeCoverageIgnoreEnd
}
/**
* Complete the authorisation code grant
*
* @access private
*
* @param array $authParams Array of parsed $_POST keys
* @param array $params Generated parameters from issueAccessToken()
*
* @return array Authorise request parameters
*/
private function _completeAuthCodeGrant($authParams = array(), $params = array())
{
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
}
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_POST['client_id'];
// Client secret
if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0);
}
$params['client_secret'] = (isset($authParams['client_secret'])) ?
$authParams['client_secret'] :
$_POST['client_secret'];
// Redirect URI
if ( ! isset($authParams['redirect_uri']) && ! isset($_POST['redirect_uri'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0);
}
$params['redirect_uri'] = (isset($authParams['redirect_uri'])) ?
$authParams['redirect_uri'] :
$_POST['redirect_uri'];
// Validate client ID and redirect URI
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
$params['client_secret'],
$params['redirect_uri']
);
if ($clientDetails === false) {
throw new ClientException($this->errors['invalid_client'], 8);
}
// The authorization code
if ( ! isset($authParams['code']) && ! isset($_POST['code'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'code'), 0);
}
$params['code'] = (isset($authParams['code'])) ?
$authParams['code'] :
$_POST['code'];
// Verify the authorization code matches the client_id and the request_uri
$session = $this->_dbCall(
'validateAuthCode',
$params['client_id'],
$params['redirect_uri'],
$params['code']
);
if ( ! $session) {
throw new ClientException(sprintf($this->errors['invalid_grant'], 'code'), 9);
}
// A session ID was returned so update it with an access token,
// remove the authorisation code, change the stage to 'granted'
$accessToken = $this->_generateCode();
$refreshToken = ($this->_grantTypes['refresh_token']) ?
$this->_generateCode() :
null;
$accessTokenExpires = time() + $this->_config['access_token_ttl'];
$accessTokenExpiresIn = $this->_config['access_token_ttl'];
$this->_dbCall(
'updateSession',
$session['id'],
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
// Update the session's scopes to reference the access token
$this->_dbCall(
'updateSessionScopeAccessToken',
$session['id'],
$accessToken,
$refreshToken
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if ($this->_grantTypes['refresh_token']) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
/**
* Complete the resource owner password credentials grant
*
* @access private
* @param array $authParams Array of parsed $_POST keys
* @param array $params Generated parameters from issueAccessToken()
* @return array Authorise request parameters
*/
private function _completeClientCredentialsGrant($authParams = array(), $params = array())
{
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_POST['client_id'];
// Client secret
if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_secret'] = (isset($authParams['client_secret'])) ?
$authParams['client_secret'] :
$_POST['client_secret'];
// Validate client ID and client secret
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
$params['client_secret'],
null
);
if ($clientDetails === false) {
// @codeCoverageIgnoreStart
throw new ClientException($this->errors['invalid_client'], 8);
// @codeCoverageIgnoreEnd
}
// Generate an access token
$accessToken = $this->_generateCode();
$refreshToken = ($this->_grantTypes['refresh_token']) ?
$this->_generateCode() :
null;
$accessTokenExpires = time() + $this->_config['access_token_ttl'];
$accessTokenExpiresIn = $this->_config['access_token_ttl'];
// Delete any existing sessions just to be sure
$this->_dbCall('deleteSession', $params['client_id'], 'client', $params['client_id']);
// Create a new session
$this->_dbCall('newSession', $params['client_id'], null, 'client', $params['client_id'], null, $accessToken, $refreshToken, $accessTokenExpires, 'granted');
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if ($this->_grantTypes['refresh_token']) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
/**
* Complete the resource owner password credentials grant
*
* @access private
* @param array $authParams Array of parsed $_POST keys
* @param array $params Generated parameters from issueAccessToken()
* @return array Authorise request parameters
*/
private function _completeUserCredentialsGrant($authParams = array(), $params = array())
{
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_POST['client_id'];
// Client secret
if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_secret'] = (isset($authParams['client_secret'])) ?
$authParams['client_secret'] :
$_POST['client_secret'];
// Validate client ID and client secret
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
$params['client_secret'],
null
);
if ($clientDetails === false) {
// @codeCoverageIgnoreStart
throw new ClientException($this->errors['invalid_client'], 8);
// @codeCoverageIgnoreEnd
}
// User's username
if ( ! isset($authParams['username']) && ! isset($_POST['username'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'username'), 0);
}
$params['username'] = (isset($authParams['username'])) ?
$authParams['username'] :
$_POST['username'];
// User's password
if ( ! isset($authParams['password']) && ! isset($_POST['password'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'password'), 0);
}
$params['password'] = (isset($authParams['password'])) ?
$authParams['password'] :
$_POST['password'];
// Check if user's username and password are correct
$userId = call_user_func($this->_grantTypeCallbacks['password'], $params['username'], $params['password']);
if ($userId === false) {
throw new \Oauth2\Authentication\ClientException($this->errors['invalid_credentials'], 0);
}
// Generate an access token
$accessToken = $this->_generateCode();
$refreshToken = ($this->_grantTypes['refresh_token']) ?
$this->_generateCode() :
null;
$accessTokenExpires = time() + $this->_config['access_token_ttl'];
$accessTokenExpiresIn = $this->_config['access_token_ttl'];
// Delete any existing sessions just to be sure
$this->_dbCall('deleteSession', $params['client_id'], 'user', $userId);
// Create a new session
$this->_dbCall('newSession', $params['client_id'], null, 'user', $userId, null, $accessToken, $refreshToken, $accessTokenExpires, 'granted');
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if ($this->_grantTypes['refresh_token']) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
/**
* Complete the refresh token grant
*
* @access private
* @param array $authParams Array of parsed $_POST keys
* @param array $params Generated parameters from issueAccessToken()
* @return array Authorise request parameters
*/
private function _completeRefreshTokenGrant($authParams = array(), $params = array())
{
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_POST['client_id'];
// Client secret
if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) {
// @codeCoverageIgnoreStart
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0);
// @codeCoverageIgnoreEnd
}
$params['client_secret'] = (isset($authParams['client_secret'])) ?
$authParams['client_secret'] :
$_POST['client_secret'];
// Validate client ID and client secret
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
$params['client_secret'],
null
);
if ($clientDetails === false) {
// @codeCoverageIgnoreStart
throw new ClientException($this->errors['invalid_client'], 8);
// @codeCoverageIgnoreEnd
}
// Refresh token
if ( ! isset($authParams['refresh_token']) && ! isset($_POST['refresh_token'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'refresh_token'), 0);
}
$params['refresh_token'] = (isset($authParams['refresh_token'])) ?
$authParams['refresh_token'] :
$_POST['refresh_token'];
// Validate refresh token
$sessionId = $this->_dbCall('validateRefreshToken', $params['refresh_token'], $params['client_id']);
if ($sessionId === false) {
throw new \Oauth2\Authentication\ClientException($this->errors['invalid_refresh'], 0);
}
// Generate new tokens
$accessToken = $this->_generateCode();
$refreshToken = $this->_generateCode();
$accessTokenExpires = time() + $this->_config['access_token_ttl'];
$accessTokenExpiresIn = $this->_config['access_token_ttl'];
// Update the tokens
$this->_dbCall('updateRefreshToken', $sessionId, $accessToken, $refreshToken, $accessTokenExpires);
return array(
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
}
/**
* Generates the redirect uri with appended params
*
* @param string $redirectUri The redirect URI
* @param array $params The parameters to be appended to the URL
* @param string $query_delimeter The query string delimiter (default: ?)
*
* @return string The updated redirect URI
*/
public function redirectUri($redirectUri, $params = array(), $queryDelimeter = '?')
{
return (strstr($redirectUri, $queryDelimeter)) ? $redirectUri . '&' . http_build_query($params) : $redirectUri . $queryDelimeter . http_build_query($params);
}
/**
* Call database methods from the abstractor
*
* @return mixed The query result
*/
private function _dbCall()
{
if ($this->_db === null) {
throw new ServerException('No registered database abstractor');
}
if ( ! $this->_db instanceof Database) {
throw new ServerException('Registered database abstractor is not an instance of Oauth2\Authentication\Database');
}
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$params = array_values($args);
return call_user_func_array(array($this->_db, $method), $params);
}
}

View File

@ -1,59 +0,0 @@
<?php
namespace Oauth2\Resource;
interface Database
{
/**
* Validate an access token and return the session details.
*
* Database query:
*
* <code>
* SELECT id, owner_type, owner_id FROM oauth_sessions WHERE access_token =
* $accessToken AND stage = 'granted' AND
* access_token_expires > UNIX_TIMESTAMP(now())
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The session ID
* [owner_type] => (string) The session owner type
* [owner_id] => (string) The session owner's ID
* )
* </code>
*
* @param string $accessToken The access token
* @return array|bool Return an array on success or false on failure
*/
public function validateAccessToken($accessToken);
/**
* Returns the scopes that the session is authorised with.
*
* Database query:
*
* <code>
* SELECT scope FROM oauth_session_scopes WHERE session_id =
* $sessionId
* </code>
*
* Response:
*
* <code>
* Array
* (
* [0] => (string) A scope
* [1] => (string) Another scope
* ...
* )
* </code>
*
* @param int $sessionId The session ID
* @return array A list of scopes
*/
public function sessionScopes($sessionId);
}

View File

@ -1,253 +0,0 @@
<?php
namespace Oauth2\Resource;
class ServerException extends \Exception
{
}
class ClientException extends \Exception
{
}
class Server
{
/**
* Reference to the database abstractor
* @var object
*/
private $_db = null;
/**
* The access token.
* @access private
*/
private $_accessToken = null;
/**
* The scopes the access token has access to.
* @access private
*/
private $_scopes = array();
/**
* The type of owner of the access token.
* @access private
*/
private $_type = null;
/**
* The ID of the owner of the access token.
* @access private
*/
private $_typeId = null;
/**
* Server configuration
* @var array
*/
private $_config = array(
'token_key' => 'oauth_token'
);
/**
* Error codes.
*
* To provide i8ln errors just overwrite the keys
*
* @var array
*/
public $errors = array(
'missing_access_token' => 'An access token was not presented with the request',
'invalid_access_token' => 'The access token is not registered with the resource server',
'missing_access_token_details' => 'The registered database abstractor did not return a valid access token details response',
'invalid_access_token_scopes' => 'The registered database abstractor did not return a valid access token scopes response',
);
/**
* Constructor
*
* @access public
* @return void
*/
public function __construct($options = null)
{
if ($options !== null) {
$this->_config = array_merge($this->_config, $options);
}
}
/**
* Magic method to test if access token represents a particular owner type
* @param string $method The method name
* @param mixed $arguements The method arguements
* @return bool If method is valid, and access token is owned by the requested party then true,
*/
public function __call($method, $arguements = null)
{
if (substr($method, 0, 2) === 'is') {
if ($this->_type === strtolower(substr($method, 2))) {
return $this->_typeId;
}
return false;
}
trigger_error('Call to undefined function ' . $method . '()');
}
/**
* Register a database abstrator class
*
* @access public
* @param object $db A class that implements OAuth2ServerDatabase
* @return void
*/
public function registerDbAbstractor($db)
{
$this->_db = $db;
}
/**
* Init function
*
* @access public
* @return void
*/
public function init()
{
$accessToken = null;
$_SERVER['REQUEST_METHOD'] = isset($_SERVER['REQUEST_METHOD']) ?
$_SERVER['REQUEST_METHOD'] :
null;
// Try and get the access token via an access_token or oauth_token parameter
switch ($_SERVER['REQUEST_METHOD'])
{
case 'POST':
$accessToken = isset($_POST[$this->_config['token_key']]) ?
$_POST[$this->_config['token_key']] :
null;
break;
default:
$accessToken = isset($_GET[$this->_config['token_key']]) ?
$_GET[$this->_config['token_key']] :
null;
break;
}
// Try and get an access token from the auth header
if (function_exists('getallheaders')) {
$headers = getallheaders();
if (isset($headers['Authorization'])) {
$rawToken = trim(str_replace('Bearer', '', $headers['Authorization']));
if ( ! empty($rawToken)) {
$accessToken = $rawToken;
}
}
}
if ($accessToken) {
$result = $this->_dbCall('validateAccessToken', $accessToken);
if ($result === false) {
throw new ClientException($this->errors['invalid_access_token']);
} else {
if ( ! array_key_exists('id', $result) ||
! array_key_exists('owner_id', $result) ||
! array_key_exists('owner_type', $result)) {
throw new ServerException($this->errors['missing_access_token_details']);
}
$this->_accessToken = $accessToken;
$this->_type = $result['owner_type'];
$this->_typeId = $result['owner_id'];
// Get the scopes
$scopes = $this->_dbCall('sessionScopes', $result['id']);
if ( ! is_array($scopes))
{
throw new ServerException($this->errors['invalid_access_token_scopes']);
}
$this->_scopes = $scopes;
}
} else {
throw new ClientException($this->errors['missing_access_token']);
}
}
/**
* Test if the access token has a specific scope
*
* @param mixed $scopes Scope(s) to check
*
* @access public
* @return string|bool
*/
public function hasScope($scopes)
{
if (is_string($scopes)) {
if (in_array($scopes, $this->_scopes)) {
return true;
}
return false;
} elseif (is_array($scopes)) {
foreach ($scopes as $scope) {
if ( ! in_array($scope, $this->_scopes)) {
return false;
}
}
return true;
}
return false;
}
/**
* Call database methods from the abstractor
*
* @return mixed The query result
*/
private function _dbCall()
{
if ($this->_db === null) {
throw new ServerException('No registered database abstractor');
}
if ( ! $this->_db instanceof Database) {
throw new ServerException('The registered database abstractor is not an instance of Oauth2\Resource\Database');
}
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$params = array_values($args);
return call_user_func_array(array($this->_db, $method), $params);
}
}

View File

@ -0,0 +1,941 @@
<?php
use \Mockery as m;
class Authentication_Server_test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\AuthServer($this->client, $this->session, $this->scope);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct_NoStorage()
{
$a = new OAuth2\AuthServer;
}
public function test__contruct_WithStorage()
{
$a = $this->returnDefault();
}
public function test_getExceptionMessage()
{
$m = OAuth2\AuthServer::getExceptionMessage('access_denied');
$reflector = new ReflectionClass($this->returnDefault());
$exceptionMessages = $reflector->getProperty('exceptionMessages');
$exceptionMessages->setAccessible(true);
$v = $exceptionMessages->getValue();
$this->assertEquals($v['access_denied'], $m);
}
public function test_hasGrantType()
{
$this->assertFalse(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_addGrantType()
{
$a = $this->returnDefault();
$grant = M::mock('OAuth2\Grant\GrantTypeInterface');
$grant->shouldReceive('getResponseType')->andReturn('test');
$a->addGrantType($grant, 'test');
$this->assertTrue(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_addGrantType_noIdentifier()
{
$a = $this->returnDefault();
$grant = M::mock('OAuth2\Grant\GrantTypeInterface');
$grant->shouldReceive('getIdentifier')->andReturn('test');
$grant->shouldReceive('getResponseType')->andReturn('test');
$a->addGrantType($grant);
$this->assertTrue(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_getScopeDelimeter()
{
$a = $this->returnDefault();
$this->assertEquals(',', $a->getScopeDelimeter());
}
public function test_setScopeDelimeter()
{
$a = $this->returnDefault();
$a->setScopeDelimeter(';');
$this->assertEquals(';', $a->getScopeDelimeter());
}
public function test_getExpiresIn()
{
$a = $this->returnDefault();
$a->setExpiresIn(7200);
$this->assertEquals(7200, $a::getExpiresIn());
}
public function test_setExpiresIn()
{
$a = $this->returnDefault();
$a->setScopeDelimeter(';');
$this->assertEquals(';', $a->getScopeDelimeter());
}
public function test_setRequest()
{
$a = $this->returnDefault();
$request = new OAuth2\Util\Request();
$a->setRequest($request);
$reflector = new ReflectionClass($a);
$requestProperty = $reflector->getProperty('request');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getRequest()
{
$a = $this->returnDefault();
$request = new OAuth2\Util\Request();
$a->setRequest($request);
$v = $a::getRequest();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getStorage()
{
$a = $this->returnDefault();
$this->assertTrue($a->getStorage('session') instanceof OAuth2\Storage\SessionInterface);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_noClientId()
{
$a = $this->returnDefault();
$a->checkAuthoriseParams();
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_noRedirectUri()
{
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_checkAuthoriseParams_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_missingResponseType()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 3
*/
public function test_checkAuthoriseParams_badResponseType()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'foo'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_missingScopes()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => ''
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 4
*/
public function test_checkAuthoriseParams_badScopes()
{
$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(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => 'foo'
));
}
public function test_checkAuthoriseParams_passedInput()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$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'
));
$v = $a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => 'foo'
));
$this->assertEquals(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
), $v);
}
public function test_checkAuthoriseParams()
{
$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();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$_GET['client_id'] = 1234;
$_GET['redirect_uri'] = 'http://foo/redirect';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'foo';
$request = new OAuth2\Util\Request($_GET);
$a->setRequest($request);
$v = $a->checkAuthoriseParams();
$this->assertEquals(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
), $v);
}
function test_newAuthoriseRequest()
{
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$a = $this->returnDefault();
$params = array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
);
$v = $a->newAuthoriseRequest('user', 123, $params);
$this->assertEquals(40, strlen($v));
}
public function test_getGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$reflector = new ReflectionClass($a);
$method = $reflector->getMethod('getGrantType');
$method->setAccessible(true);
$result = $method->invoke($a, 'authorization_code');
$this->assertTrue($result instanceof OAuth2\Grant\GrantTypeInterface);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken();
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 7
*/
public function test_issueAccessToken_badGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array('grant_type' => 'foo'));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingClientSecret()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingRedirectUri()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingCode()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 9
*/
public function test_issueAccessToken_badCode()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$this->session->shouldReceive('validateAuthCode')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'code' => 'foobar'
));
}
public function test_issueAccessToken_passedInput()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'code' => 'foobar'
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function test_issueAccessToken()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$_POST['grant_type'] = 'authorization_code';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['redirect_uri'] = 'http://foo/redirect';
$_POST['code'] = 'foobar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function test_issueAccessToken_with_refresh_token()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'authorization_code';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['redirect_uri'] = 'http://foo/redirect';
$_POST['code'] = 'foobar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingClientSecret()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_refreshTokenGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
//'refresh_token' =>
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_badRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$this->client->shouldReceive('validateRefreshToken')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
'refresh_token' => 'abcdef'
));
}
public function test_issueAccessToken_refreshTokenGrant_passedInput()
{
$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('updateSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'refresh_token';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['refresh_token'] = 'abcdef';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function test_issueAccessToken_refreshTokenGrant()
{
$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('updateSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$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);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_clientCredentialsGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_clientCredentialsGrant_missingClientCredentials()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_clientCredentialsGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234,
'client_secret' => 5678
));
}
function test_issueAccessToken_clientCredentialsGrant_passedInput()
{
$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);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234,
'client_secret' => 5678
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_clientCredentialsGrant()
{
$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);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$_POST['grant_type'] = 'client_credentials';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function tearDown() {
M::close();
}
}

View File

@ -1,168 +0,0 @@
<?php
use Oauth2\Authentication\Database;
class OAuthdb implements Database
{
private $sessions = array();
private $sessions_client_type_id = array();
private $sessions_code = array();
private $session_scopes = array();
private $clients = array(0 => array(
'client_id' => 'test',
'client_secret' => 'test',
'redirect_uri' => 'http://example.com/test',
'name' => 'Test Client'
));
private $scopes = array('test' => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
));
public function validateClient($clientId, $clientSecret = null, $redirectUri = null)
{
if ($clientId !== $this->clients[0]['client_id']) {
return false;
}
if ($clientSecret !== null && $clientSecret !== $this->clients[0]['client_secret']) {
return false;
}
if ($redirectUri !== null && $redirectUri !== $this->clients[0]['redirect_uri']) {
return false;
}
return $this->clients[0];
}
public function newSession($clientId, $redirectUri, $type = 'user', $typeId = null, $authCode = null, $accessToken = null, $refreshToken = null, $accessTokenExpire = null, $stage = 'requested')
{
$id = count($this->sessions);
$this->sessions[$id] = array(
'id' => $id,
'client_id' => $clientId,
'redirect_uri' => $redirectUri,
'owner_type' => $type,
'owner_id' => $typeId,
'auth_code' => $authCode,
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'access_token_expire' => $accessTokenExpire,
'stage' => $stage
);
$this->sessions_client_type_id[$clientId . ':' . $type . ':' . $typeId] = $id;
$this->sessions_code[$clientId . ':' . $redirectUri . ':' . $authCode] = $id;
return $id;
}
public function updateSession($sessionId, $authCode = null, $accessToken = null, $refreshToken = null, $accessTokenExpire = null, $stage = 'requested')
{
$this->sessions[$sessionId]['auth_code'] = $authCode;
$this->sessions[$sessionId]['access_token'] = $accessToken;
$this->sessions[$sessionId]['refresh_token'] = $refreshToken;
$this->sessions[$sessionId]['access_token_expire'] = $accessTokenExpire;
$this->sessions[$sessionId]['stage'] = $stage;
return true;
}
public function deleteSession($clientId, $type, $typeId)
{
$key = $clientId . ':' . $type . ':' . $typeId;
if (isset($this->sessions_client_type_id[$key])) {
unset($this->sessions[$this->sessions_client_type_id[$key]]);
}
return true;
}
public function refreshToken($currentRefreshToken, $newAccessToken, $newRefreshToken, $accessTokenExpires)
{
die('not implemented refreshToken');
}
public function validateAuthCode($clientId, $redirectUri, $authCode)
{
$key = $clientId . ':' . $redirectUri . ':' . $authCode;
if (isset($this->sessions_code[$key])) {
return $this->sessions[$this->sessions_code[$key]];
}
return false;
}
public function hasSession($type, $typeId, $clientId)
{
die('not implemented hasSession');
}
public function getAccessToken($sessionId)
{
die('not implemented getAccessToken');
}
public function removeAuthCode($sessionId)
{
die('not implemented removeAuthCode');
}
public function setAccessToken($sessionId, $accessToken)
{
die('not implemented setAccessToken');
}
public function addSessionScope($sessionId, $scope)
{
if ( ! isset($this->session_scopes[$sessionId])) {
$this->session_scopes[$sessionId] = array();
}
$this->session_scopes[$sessionId][] = $scope;
return true;
}
public function getScope($scope)
{
if ( ! isset($this->scopes[$scope])) {
return false;
}
return $this->scopes[$scope];
}
public function updateSessionScopeAccessToken($sessionId, $accessToken)
{
return true;
}
public function accessTokenScopes($accessToken)
{
die('not implemented accessTokenScopes');
}
public function validateRefreshToken($refreshToken, $clientId)
{
if ($refreshToken !== $this->sessions[0]['refresh_token'])
{
return false;
}
return true;
}
public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires)
{
$this->sessions[$sessionId]['access_token'] = $newAccessToken;
$this->sessions[$sessionId]['refresh_token'] = $newRefreshToken;
$this->sessions[$sessionId]['access_token_expire'] = $accessTokenExpires;
}
}

View File

@ -1,912 +0,0 @@
<?php
class Authentication_Server_test extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->oauth = new Oauth2\Authentication\Server();
require_once 'database_mock.php';
$this->oauthdb = new OAuthdb();
$this->assertInstanceOf('Oauth2\Authentication\Database', $this->oauthdb);
$this->oauth->registerDbAbstractor($this->oauthdb);
}
public function test_setupWithOptions()
{
$o = new Oauth2\Authentication\Server(array(
'access_token_ttl' => 86400
));
$reflector = new ReflectionClass($o);
$param = $reflector->getProperty('_config');
$param->setAccessible(true);
$array = $param->getValue($o);
$this->assertEquals(86400, $array['access_token_ttl']);
}
public function test_generateCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_generateCode');
$method->setAccessible(true);
$result = $method->invoke($this->oauth);
$result2 = $method->invoke($this->oauth);
$this->assertEquals(40, strlen($result));
$this->assertNotEquals($result, $result2);
}
public function test_redirectUri()
{
$result1 = $this->oauth->redirectUri('http://example.com/foo');
$result2 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar'));
$result3 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar'), '#');
$this->assertEquals('http://example.com/foo?', $result1);
$this->assertEquals('http://example.com/foo?foo=bar', $result2);
$this->assertEquals('http://example.com/foo#foo=bar', $result3);
}
public function test_checkClientAuthoriseParams_GET()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'test';
$expect = array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'client_details' => array(
'client_id' => 'test',
'client_secret' => 'test',
'redirect_uri' => 'http://example.com/test',
'name' => 'Test Client'
),
'response_type' => 'code',
'scopes' => array(
0 => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
)
)
);
$result = $this->oauth->checkClientAuthoriseParams();
$this->assertEquals($expect, $result);
}
public function test_checkClientAuthoriseParams_PassedParams()
{
unset($_GET['client_id']);
unset($_GET['redirect_uri']);
unset($_GET['response_type']);
unset($_GET['scope']);
$params = array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'response_type' => 'code',
'scope' => 'test'
);
$this->assertEquals(array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'client_details' => array(
'client_id' => 'test',
'client_secret' => 'test',
'redirect_uri' => 'http://example.com/test',
'name' => 'Test Client'
),
'response_type' => 'code',
'scopes' => array(0 => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
), $this->oauth->checkClientAuthoriseParams($params));
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_checkClientAuthoriseParams_missingClientId()
{
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_checkClientAuthoriseParams_missingRedirectUri()
{
$_GET['client_id'] = 'test';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_checkClientAuthoriseParams_missingResponseType()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_checkClientAuthoriseParams_missingScopes()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = ' ';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 4
*/
public function test_checkClientAuthoriseParams_invalidScopes()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'blah';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 8
*/
public function test_checkClientAuthoriseParams_invalidClient()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test2';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'blah';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 3
*/
public function test_checkClientAuthoriseParams_invalidResponseType()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'blah';
$_GET['scope'] = 'blah';
$this->oauth->checkClientAuthoriseParams();
}
public function test_newAuthoriseRequest()
{
$result = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$this->assertEquals(40, strlen($result));
}
public function test_newAuthoriseRequest_isUnique()
{
$result1 = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$result2 = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$this->assertNotEquals($result1, $result2);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 7
*/
public function test_issueAccessTokenNoRegisteredGrant()
{
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'authorization_code';
$_POST['code'] = $auth_code;
$result = $this->oauth->issueAccessToken();
}
public function test_issueAccessToken_POST_authorization_code()
{
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'authorization_code';
$_POST['code'] = $auth_code;
$this->oauth->enableGrantType('authorization_code');
$result = $this->oauth->issueAccessToken();
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_PassedParams_authorization_code()
{
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'authorization_code';
$params['code'] = $auth_code;
$this->oauth->enableGrantType('authorization_code');
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_refresh_token()
{
$this->oauth->enableGrantType('authorization_code');
$this->oauth->enableGrantType('refresh_token');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'authorization_code';
$params['code'] = $auth_code;
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
// Wait for a few seconds for the access token to age
sleep(1);
// Refresh the token
$params2['client_id'] = 'test';
$params2['client_secret'] = 'test';
$params2['redirect_uri'] = 'http://example.com/test';
$params2['grant_type'] = 'refresh_token';
$params2['refresh_token'] = $result['refresh_token'];
$result2 = $this->oauth->issueAccessToken($params2);
$this->assertCount(5, $result2);
$this->assertArrayHasKey('access_token', $result2);
$this->assertArrayHasKey('token_type', $result2);
$this->assertArrayHasKey('expires_in', $result2);
$this->assertArrayHasKey('expires', $result2);
$this->assertArrayHasKey('refresh_token', $result2);
$this->assertNotEquals($result['access_token'], $result2['access_token']);
$this->assertNotEquals($result['refresh_token'], $result2['refresh_token']);
$this->assertNotEquals($result['expires'], $result2['expires']);
$this->assertEquals($result['expires_in'], $result2['expires_in']);
$this->assertEquals($result['token_type'], $result2['token_type']);
}
public function test_issueAccessToken_client_credentials()
{
$this->oauth->enableGrantType('client_credentials');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'client_credentials';
$params['code'] = $auth_code;
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_client_credentialsPOST()
{
$this->oauth->enableGrantType('client_credentials');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'client_credentials';
$_POST['code'] = $auth_code;
$result = $this->oauth->issueAccessToken();
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_client_credentials_withRefreshToken()
{
$this->oauth->enableGrantType('client_credentials');
$this->oauth->enableGrantType('refresh_token');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'client_credentials';
$params['code'] = $auth_code;
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
}
public function test_issueAccessToken_refresh_tokenPOST()
{
$this->oauth->enableGrantType('authorization_code');
$this->oauth->enableGrantType('refresh_token');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'authorization_code';
$_POST['code'] = $auth_code;
$result = $this->oauth->issueAccessToken();
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
// Wait for a few seconds for the access token to age
sleep(1);
// Refresh the token
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'refresh_token';
$_POST['refresh_token'] = $result['refresh_token'];
$result2 = $this->oauth->issueAccessToken();
$this->assertCount(5, $result2);
$this->assertArrayHasKey('access_token', $result2);
$this->assertArrayHasKey('token_type', $result2);
$this->assertArrayHasKey('expires_in', $result2);
$this->assertArrayHasKey('expires', $result2);
$this->assertArrayHasKey('refresh_token', $result2);
$this->assertNotEquals($result['access_token'], $result2['access_token']);
$this->assertNotEquals($result['refresh_token'], $result2['refresh_token']);
$this->assertNotEquals($result['expires'], $result2['expires']);
$this->assertEquals($result['expires_in'], $result2['expires_in']);
$this->assertEquals($result['token_type'], $result2['token_type']);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refresh_tokenMissingToken()
{
$this->oauth->enableGrantType('authorization_code');
$this->oauth->enableGrantType('refresh_token');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'authorization_code';
$_POST['code'] = $auth_code;
$result = $this->oauth->issueAccessToken();
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
// Wait for a few seconds for the access token to age
sleep(1);
// Refresh the token
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'refresh_token';
$result2 = $this->oauth->issueAccessToken();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_invalid_refresh_token()
{
$this->oauth->enableGrantType('authorization_code');
$this->oauth->enableGrantType('refresh_token');
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'authorization_code';
$params['code'] = $auth_code;
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
// Wait for a few seconds for the access token to age
sleep(1);
// Refresh the token
$params2['client_id'] = 'test';
$params2['client_secret'] = 'test';
$params2['redirect_uri'] = 'http://example.com/test';
$params2['grant_type'] = 'refresh_token';
$params2['refresh_token'] = 'blah';
$result2 = $this->oauth->issueAccessToken($params2);
}
/**
* @expectedException Oauth2\Authentication\ServerException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_password_grant_Missing_Callback()
{
$this->oauth->enableGrantType('password');
}
public function test_issueAccessToken_password_grant()
{
$this->oauth->enableGrantType('password', function(){
return true;
});
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['grant_type'] = 'password';
$params['username'] = 'alexbilbie';
$params['password'] = 'helloworld';
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_password_grantPOST()
{
$this->oauth->enableGrantType('password', function(){
return true;
});
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['grant_type'] = 'password';
$_POST['username'] = 'alexbilbie';
$_POST['password'] = 'helloworld';
$result = $this->oauth->issueAccessToken();
$this->assertCount(4, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
}
public function test_issueAccessToken_password_grant_withRefreshToken()
{
$this->oauth->enableGrantType('password', function(){
return true;
});
$this->oauth->enableGrantType('refresh_token');
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['grant_type'] = 'password';
$params['username'] = 'alexbilbie';
$params['password'] = 'helloworld';
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(5, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
$this->assertArrayHasKey('expires', $result);
$this->assertArrayHasKey('refresh_token', $result);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_password_grant_wrongCreds()
{
$this->oauth->enableGrantType('password', function(){
return false;
});
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['grant_type'] = 'password';
$params['username'] = 'alexbilbie';
$params['password'] = 'helloworld';
$result = $this->oauth->issueAccessToken($params);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_password_grant_missingUsername()
{
$this->oauth->enableGrantType('password', function(){
return true;
});
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['grant_type'] = 'password';
$result = $this->oauth->issueAccessToken($params);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_password_grant_missingPassword()
{
$this->oauth->enableGrantType('password', function(){
return true;
});
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['grant_type'] = 'password';
$params['username'] = 'alexbilbie';
$result = $this->oauth->issueAccessToken($params);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingGrantType()
{
$this->oauth->issueAccessToken();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 7
*/
public function test_issueAccessToken_unsupportedGrantType()
{
$params['grant_type'] = 'blah';
$this->oauth->issueAccessToken($params);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_completeAuthCodeGrant_missingClientId()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$method->invoke($this->oauth);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_completeAuthCodeGrant_missingClientSecret()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_completeAuthCodeGrant_missingRedirectUri()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 8
*/
public function test_completeAuthCodeGrant_invalidClient()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test123';
$authParams['redirect_uri'] = 'http://example.com/test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
public function test_completeAuthCodeGrant_missingCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$authParams['redirect_uri'] = 'http://example.com/test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 9
*/
public function test_completeAuthCodeGrant_invalidCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$authParams['redirect_uri'] = 'http://example.com/test';
$authParams['code'] = 'blah';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ServerException
* @expectedExceptionMessage No registered database abstractor
*/
public function test_noRegisteredDatabaseAbstractor()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_dbCall');
$method->setAccessible(true);
$dbAbstractor = $reflector->getProperty('_db');
$dbAbstractor->setAccessible(true);
$dbAbstractor->setValue($this->oauth, null);
$result = $method->invoke($this->oauth);
}
/**
* @expectedException Oauth2\Authentication\ServerException
* @expectedExceptionMessage Registered database abstractor is not an instance of Oauth2\Authentication\Database
*/
public function test_invalidRegisteredDatabaseAbstractor()
{
$fake = new stdClass;
$this->oauth->registerDbAbstractor($fake);
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_dbCall');
$method->setAccessible(true);
$result = $method->invoke($this->oauth);
}
}

View File

@ -0,0 +1,159 @@
<?php
use \Mockery as m;
class Resource_Server_test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
//$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\ResourceServer($this->session);
}
public function test_setRequest()
{
$s = $this->returnDefault();
$request = new OAuth2\Util\Request();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$requestProperty = $reflector->getProperty('request');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue($s);
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getRequest()
{
$s = $this->returnDefault();
$request = new OAuth2\Util\Request();
$s->setRequest($request);
$v = $s->getRequest();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getTokenKey()
{
$s = $this->returnDefault();
$this->assertEquals('oauth_token', $s->getTokenKey());
}
public function test_setTokenKey()
{
$s = $this->returnDefault();
$s->setTokenKey('access_token');
$reflector = new ReflectionClass($s);
$requestProperty = $reflector->getProperty('tokenKey');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue($s);
$this->assertEquals('access_token', $v);
}
/**
* @expectedException OAuth2\Exception\MissingAccessTokenException
*/
public function test_determineAccessToken_missingToken()
{
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer';
$request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER);
$s = $this->returnDefault();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$result = $method->invoke($s);
}
public function test_determineAccessToken_fromHeader()
{
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef';
$request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER);
$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();
$_GET[$s->getTokenKey()] = 'abcdef';
$_SERVER['REQUEST_METHOD'] = 'get';
$request = new OAuth2\Util\Request($_GET, array(), array(), array(), $_SERVER);
$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_isValid_notValid()
{
$this->session->shouldReceive('validateAccessToken')->andReturn(false);
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef';
$request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER);
$s = $this->returnDefault();
$s->setRequest($request);
$this->assertFalse($s->isValid());
}
public function test_isValid_valid()
{
$this->session->shouldReceive('validateAccessToken')->andReturn(array(
'id' => 1,
'owner_type' => 'user',
'owner_id' => 123
));
$this->session->shouldReceive('getScopes')->andReturn(array('foo', 'bar'));
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef';
$request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER);
$s = $this->returnDefault();
$s->setRequest($request);
$this->assertTrue($s->isValid());
$this->assertEquals(123, $s->getOwnerId());
$this->assertEquals('user', $s->getOwnerType());
$this->assertEquals('abcdef', $s->getAccessToken());
$this->assertTrue($s->hasScope('foo'));
$this->assertTrue($s->hasScope('bar'));
$this->assertTrue($s->hasScope(array('foo', 'bar')));
$this->assertFalse($s->hasScope(array('foobar')));
$this->assertFalse($s->hasScope('foobar'));
$this->assertFalse($s->hasScope(new StdClass));
}
}

View File

@ -1,31 +0,0 @@
<?php
use Oauth2\Resource\Database;
class ResourceDB implements Database
{
private $accessTokens = array(
'test12345' => array(
'id' => 1,
'owner_type' => 'user',
'owner_id' => 123
)
);
private $sessionScopes = array(
1 => array(
'foo',
'bar'
)
);
public function validateAccessToken($accessToken)
{
return (isset($this->accessTokens[$accessToken])) ? $this->accessTokens[$accessToken] : false;
}
public function sessionScopes($sessionId)
{
return (isset($this->sessionScopes[$sessionId])) ? $this->sessionScopes[$sessionId] : array();
}
}

View File

@ -1,121 +0,0 @@
<?php
class Resource_Server_test extends PHPUnit_Framework_TestCase {
function setUp()
{
require_once('database_mock.php');
$this->server = new Oauth2\Resource\Server();
$this->db = new ResourceDB();
$this->assertInstanceOf('Oauth2\Resource\Database', $this->db);
$this->server->registerDbAbstractor($this->db);
}
function test_init_POST()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['oauth_token'] = 'test12345';
$this->server->init();
$reflector = new ReflectionClass($this->server);
$_accessToken = $reflector->getProperty('_accessToken');
$_accessToken->setAccessible(true);
$_type = $reflector->getProperty('_type');
$_type->setAccessible(true);
$_typeId = $reflector->getProperty('_typeId');
$_typeId->setAccessible(true);
$_scopes = $reflector->getProperty('_scopes');
$_scopes->setAccessible(true);
$this->assertEquals($_accessToken->getValue($this->server), $_POST['oauth_token']);
$this->assertEquals($_type->getValue($this->server), 'user');
$this->assertEquals($_typeId->getValue($this->server), 123);
$this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar'));
}
function test_init_GET()
{
$_GET['oauth_token'] = 'test12345';
$this->server->init();
$reflector = new ReflectionClass($this->server);
$_accessToken = $reflector->getProperty('_accessToken');
$_accessToken->setAccessible(true);
$_type = $reflector->getProperty('_type');
$_type->setAccessible(true);
$_typeId = $reflector->getProperty('_typeId');
$_typeId->setAccessible(true);
$_scopes = $reflector->getProperty('_scopes');
$_scopes->setAccessible(true);
$this->assertEquals($_accessToken->getValue($this->server), $_GET['oauth_token']);
$this->assertEquals($_type->getValue($this->server), 'user');
$this->assertEquals($_typeId->getValue($this->server), 123);
$this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar'));
}
function test_init_header()
{
// Test with authorisation header
$this->markTestIncomplete('Authorisation header test has not been implemented yet.');
}
/**
* @expectedException \Oauth2\Resource\ClientException
* @expectedExceptionMessage An access token was not presented with the request
*/
function test_init_missingToken()
{
$this->server->init();
}
/**
* @expectedException \Oauth2\Resource\ClientException
* @expectedExceptionMessage The access token is not registered with the resource server
*/
function test_init_wrongToken()
{
$_POST['oauth_token'] = 'blah';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
}
function test_hasScope()
{
$_POST['oauth_token'] = 'test12345';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
$this->assertEquals(true, $this->server->hasScope('foo'));
$this->assertEquals(true, $this->server->hasScope('bar'));
$this->assertEquals(true, $this->server->hasScope(array('foo', 'bar')));
$this->assertEquals(false, $this->server->hasScope('foobar'));
$this->assertEquals(false, $this->server->hasScope(array('foobar')));
}
function test___call()
{
$_POST['oauth_token'] = 'test12345';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
$this->assertEquals(123, $this->server->isUser());
$this->assertEquals(false, $this->server->isMachine());
}
}

View File

@ -0,0 +1,15 @@
<?php
class RedirectUri_test extends PHPUnit_Framework_TestCase
{
function test_make()
{
$v1 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar'));
$v2 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar'), '#');
$v3 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar', 'bar' => 'foo'));
$this->assertEquals('https://foobar/?foo=bar', $v1);
$this->assertEquals('https://foobar/#foo=bar', $v2);
$this->assertEquals('https://foobar/?foo=bar&bar=foo', $v3);
}
}

View File

@ -0,0 +1,73 @@
<?php
class Request_test extends PHPUnit_Framework_TestCase
{
private $request;
function setUp()
{
$this->request = new OAuth2\Util\Request(
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('HTTP_HOST' => 'foobar.com')
);
}
function test_buildFromIndex()
{
$r = new OAuth2\Util\Request();
$r->buildFromGlobals();
$this->assertTrue($r instanceof OAuth2\Util\Request);
}
function test_get()
{
$this->assertEquals('bar', $this->request->get('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->get());
}
function test_post()
{
$this->assertEquals('bar', $this->request->post('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->post());
}
function test_file()
{
$this->assertEquals('bar', $this->request->file('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->file());
}
function test_cookie()
{
$this->assertEquals('bar', $this->request->cookie('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->cookie());
}
function test_server()
{
$this->assertEquals('foobar.com', $this->request->server('HTTP_HOST'));
$this->assertEquals(array('HTTP_HOST' => 'foobar.com'), $this->request->server());
}
function test_header()
{
$this->assertEquals('foobar.com', $this->request->header('Host'));
$this->assertEquals(array('Host' => 'foobar.com'), $this->request->header());
}
/**
* @expectedException InvalidArgumentException
*/
function test_unknownProperty()
{
$reflector = new ReflectionClass($this->request);
$method = $reflector->getMethod('getPropertyValue');
$method->setAccessible(true);
$result = $method->invoke($this->request, 'blah');
}
}

View File

@ -0,0 +1,15 @@
<?php
class Secure_Key_test extends PHPUnit_Framework_TestCase
{
function test_make()
{
$v1 = OAuth2\Util\SecureKey::make();
$v2 = OAuth2\Util\SecureKey::make();
$v3 = OAuth2\Util\SecureKey::make(50);
$this->assertEquals(40, strlen($v1));
$this->assertTrue($v1 !== $v2);
$this->assertEquals(50, strlen($v3));
}
}