Merge branch 'refs/heads/develop' into feature/clients

Conflicts:
	src/Oauth2/Authentication/Server.php
This commit is contained in:
Alex Bilbie
2012-09-04 12:09:13 +01:00
10 changed files with 753 additions and 55 deletions

View File

@@ -23,13 +23,13 @@ class Server
* Reference to the database abstractor
* @var object
*/
private $db = null;
private $_db = null;
/**
* Server configuration
* @var array
*/
private $config = array(
private $_config = array(
'scope_delimeter' => ',',
'access_token_ttl' => null
);
@@ -38,7 +38,7 @@ class Server
* Supported response types
* @var array
*/
private $response_types = array(
private $_responseTypes = array(
'code'
);
@@ -46,7 +46,7 @@ class Server
* Supported grant types
* @var array
*/
private $grant_types = array(
private $_grantTypes = array(
'authorization_code'
);
@@ -97,7 +97,7 @@ class Server
public function __construct($options = null)
{
if ($options !== null) {
$this->config = array_merge($this->config, $options);
$this->options = array_merge($this->_config, $options);
}
}
@@ -110,7 +110,7 @@ class Server
*/
public function registerDbAbstractor($db)
{
$this->db = $db;
$this->_db = $db;
}
/**
@@ -147,7 +147,7 @@ class Server
}
// Validate client ID and redirect URI
$clientDetails = $this->dbcall('validateClient', $params['client_id'], null, $params['redirect_uri']);
$clientDetails = $this->_dbCall('validateClient', $params['client_id'], null, $params['redirect_uri']);
if ($clientDetails === false) {
@@ -164,7 +164,7 @@ class Server
$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->response_types)) {
if ( ! in_array($params['response_type'], $this->_responseTypes)) {
throw new OAuthServerClientException($this->errors['unsupported_response_type'], 3);
@@ -176,7 +176,7 @@ class Server
$scopes = (isset($_GET['scope'])) ? $_GET['scope'] : $authParams['scope'];
$scopes = explode($this->config['scope_delimeter'], $scopes);
$scopes = explode($this->_config['scope_delimeter'], $scopes);
// Remove any junk scopes
for ($i = 0; $i < count($scopes); $i++) {
@@ -196,8 +196,8 @@ class Server
foreach ($scopes as $scope) {
$scopeDetails = $this->dbcall('getScope', $scope);
//die(var_dump($scopeDetails));
$scopeDetails = $this->_dbCall('getScope', $scope);
if ($scopeDetails === false) {
throw new OAuthServerClientException(sprintf($this->errors['invalid_scope'], $scope), 4);
@@ -223,7 +223,7 @@ class Server
public function newAuthoriseRequest($type, $typeId, $authoriseParams)
{
// Remove any old sessions the user might have
$this->dbcall('deleteSession',
$this->_dbCall('deleteSession',
$authoriseParams['client_id'],
$type,
$typeId
@@ -272,7 +272,7 @@ class Server
// new authorisation code otherwise create a new session
if ($accessToken !== null) {
$this->dbcall('updateSession',
$this->_dbCall('updateSession',
$clientId,
$type,
$typeId,
@@ -284,10 +284,10 @@ class Server
} else {
// Delete any existing sessions just to be sure
$this->dbcall('deleteSession', $clientId, $type, $typeId);
$this->_dbCall('deleteSession', $clientId, $type, $typeId);
// Create a new session
$sessionId = $this->dbcall('newSession',
$sessionId = $this->_dbCall('newSession',
$clientId,
$redirectUri,
$type,
@@ -301,7 +301,7 @@ class Server
// Add the scopes
foreach ($scopes as $key => $scope) {
$this->dbcall('addSessionScope', $sessionId, $scope['scope']);
$this->_dbCall('addSessionScope', $sessionId, $scope['scope']);
}
@@ -332,7 +332,7 @@ class Server
$params['grant_type'] = (isset($authParams['grant_type'])) ? $authParams['grant_type'] : $_POST['grant_type'];
// Ensure grant type is one that is recognised
if ( ! in_array($params['grant_type'], $this->grant_types)) {
if ( ! in_array($params['grant_type'], $this->_grantTypes)) {
throw new OAuthServerClientException($this->errors['unsupported_grant_type'], 7);
@@ -401,7 +401,7 @@ class Server
}
// Validate client ID and redirect URI
$clientDetails = $this->dbcall('validateClient',
$clientDetails = $this->_dbCall('validateClient',
$params['client_id'],
$params['client_secret'],
$params['redirect_uri']
@@ -413,8 +413,7 @@ class Server
}
// The authorization code
if ( ! isset($authParams['code']) &&
! isset($_POST['code'])) {
if ( ! isset($authParams['code']) && ! isset($_POST['code'])) {
throw new OAuthServerClientException(sprintf($this->errors['invalid_request'], 'code'), 0);
@@ -426,7 +425,7 @@ class Server
// Verify the authorization code matches the client_id and the
// request_uri
$session = $this->dbcall('validateAuthCode',
$session = $this->_dbCall('validateAuthCode',
$params['client_id'],
$params['redirect_uri'],
$params['code']
@@ -443,9 +442,9 @@ class Server
$accessToken = $this->generateCode();
$accessTokenExpires = ($this->config['access_token_ttl'] === null) ? null : time() + $this->config['access_token_ttl'];
$accessTokenExpires = ($this->_config['access_token_ttl'] === null) ? null : time() + $this->_config['access_token_ttl'];
$this->dbcall('updateSession',
$this->_dbCall('updateSession',
$session['id'],
null,
$accessToken,
@@ -454,7 +453,7 @@ class Server
);
// Update the session's scopes to reference the access token
$this->dbcall('updateSessionScopeAccessToken',
$this->_dbCall('updateSessionScopeAccessToken',
$session['id'],
$accessToken
);
@@ -462,7 +461,7 @@ class Server
return array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires_in' => $this->config['access_token_ttl']
'expires_in' => $this->_config['access_token_ttl']
);
}
}
@@ -498,13 +497,13 @@ class Server
*
* @return mixed The query result
*/
private function dbcall()
private function _dbCall()
{
if ($this->db === null) {
if ($this->_db === null) {
throw new OAuthServerException('No registered database abstractor');
}
if ( ! $this->db instanceof Database) {
if ( ! $this->_db instanceof Database) {
throw new OAuthServerException('Registered database abstractor is not an instance of Oauth2\Authentication\Database');
}
@@ -513,6 +512,6 @@ class Server
unset($args[0]);
$params = array_values($args);
return call_user_func_array(array($this->db, $method), $args);
return call_user_func_array(array($this->_db, $method), $params);
}
}

View File

@@ -4,4 +4,56 @@ 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 access_token =
* '291dca1c74900f5f252de351e0105aa3fc91b90b'
* </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

@@ -2,7 +2,227 @@
namespace Oauth2\Resource;
class OAuthResourceServerException 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'
);
/**
* 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 = base64_decode($rawToken);
}
}
}
if ($accessToken) {
$result = $this->_dbCall('validateAccessToken', $accessToken);
if ($result === false) {
throw new OAuthResourceServerException($this->errors['invalid_access_token']);
} else {
$this->_accessToken = $accessToken;
$this->_type = $result['owner_type'];
$this->_typeId = $result['owner_id'];
// Get the scopes
$this->_scopes = $this->_dbCall('sessionScopes', $result['id']);
}
} else {
throw new OAuthResourceServerException($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 OAuthResourceServerException('No registered database abstractor');
}
if ( ! $this->_db instanceof Database) {
throw new OAuthResourceServerException('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);
}
}