Merge branch 'release/1.0.0'

This commit is contained in:
Alex Bilbie 2013-02-15 17:09:24 +00:00
commit 52bdc79f79
57 changed files with 3376 additions and 3750 deletions

4
.gitignore vendored
View File

@ -3,4 +3,6 @@
/docs/build/ /docs/build/
/build/logs/ /build/logs/
/build/coverage/ /build/coverage/
test test
/docs/
/testing/

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

5
CHANGELOG.md Normal file
View File

@ -0,0 +1,5 @@
# Changelog
## 1.0.0 (released 2012-02-15)
* First release

View File

@ -1,6 +1,6 @@
# PHP OAuth Framework # PHP OAuth Framework
The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server, resource server and client library with support for a major OAuth 2 providers. The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server and resource server.
## Package Installation ## Package Installation
@ -9,33 +9,30 @@ The framework is provided as a Composer package which can be installed by adding
```javascript ```javascript
{ {
"require": { "require": {
"lncd\Oauth2": "*" "lncd\OAuth2": "*"
} }
} }
``` ```
## Package Integration ---
Check out the [wiki](https://github.com/lncd/OAuth2/wiki) The library features 100% unit test code coverage. To run the tests yourself run `phpunit -c build/phpunit.xml`.
## Current Features ## Current Features
### Authentication Server ### Authentication Server
The authentication server is a flexible class that supports the following grants: The authentication server is a flexible class and following core specification grants are implemented:
* authentication code * authentication code ([section 4.1](http://tools.ietf.org/html/rfc6749#section-4.1))
* refresh token * refresh token ([section 6](http://tools.ietf.org/html/rfc6749#section-6))
* client credentials * client credentials ([section 2.3.1](http://tools.ietf.org/html/rfc6749#section-2.3.1))
* password (user credentials) * password (user credentials) ([section 4.3](http://tools.ietf.org/html/rfc6749#section-4.3))
### Resource Server ### Resource Server
The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct permission to access resources. The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct permission to access resources.
## Future Goals ## Future Goals
### Authentication Server ### Authentication Server
@ -43,10 +40,13 @@ The resource server allows you to secure your API endpoints by checking for a va
* Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/). * Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/).
* Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/). * Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/).
### Client support
* Merge in https://github.com/philsturgeon/codeigniter-oauth2
--- ---
This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme. This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme.
This code was principally developed by [Alex Bilbie](http://alexbilbie.com/) ([Twitter](https://twitter.com/alexbilbie)|[Github](https://github.com/alexbilbie)).
Valuable contribtions have been made by the following:
* [Dan Horrigan](http://dandoescode.com) ([Twitter](https://twitter.com/dandoescode)|[Github](https://github.com/dandoescode))
* [Nick Jackson](http://nickjackson.me) ([Twitter](https://twitter.com/jacksonj04)|[Github](https://github.com/jacksonj04))

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,10 @@
<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">../vendor/phpunit</directory>
<directory suffix=".php">../tests</directory> <directory suffix=".php">../tests</directory>
<directory suffix=".php">../testing</directory>
</blacklist> </blacklist>
</filter> </filter>
<logging> <logging>

View File

@ -1,5 +1,13 @@
-- Create syntax for TABLE 'clients' CREATE TABLE `oauth_client_endpoints` (
CREATE TABLE `clients` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '',
`redirect_uri` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `client_id` (`client_id`),
CONSTRAINT `oauth_client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_clients` (
`id` varchar(40) NOT NULL DEFAULT '', `id` varchar(40) NOT NULL DEFAULT '',
`secret` varchar(40) NOT NULL DEFAULT '', `secret` varchar(40) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
@ -7,26 +15,26 @@ CREATE TABLE `clients` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'client_endpoints' CREATE TABLE `oauth_session_scopes` (
CREATE TABLE `client_endpoints` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '', `session_id` int(11) unsigned NOT NULL,
`redirect_uri` varchar(255) DEFAULT NULL, `scope_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `client_id` (`client_id`), KEY `session_id` (`session_id`),
CONSTRAINT `client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE KEY `scope_id` (`scope_id`),
CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`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;
-- Create syntax for TABLE 'oauth_sessions'
CREATE TABLE `oauth_sessions` ( CREATE TABLE `oauth_sessions` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '', `client_id` varchar(40) NOT NULL DEFAULT '',
`redirect_uri` varchar(250) DEFAULT '', `redirect_uri` varchar(250) DEFAULT '',
`owner_type` enum('user','client') NOT NULL DEFAULT 'user', `owner_type` enum('user','client') NOT NULL DEFAULT 'user',
`owner_id` varchar(255) DEFAULT NULL, `owner_id` varchar(255) DEFAULT '',
`auth_code` varchar(40) DEFAULT '', `auth_code` varchar(40) DEFAULT '',
`access_token` varchar(40) DEFAULT '', `access_token` varchar(40) DEFAULT '',
`refresh_token` varchar(40) NOT NULL, `refresh_token` varchar(40) DEFAULT '',
`access_token_expires` int(10) DEFAULT NULL, `access_token_expires` int(10) DEFAULT NULL,
`stage` enum('requested','granted') NOT NULL DEFAULT 'requested', `stage` enum('requested','granted') NOT NULL DEFAULT 'requested',
`first_requested` int(10) unsigned NOT NULL, `first_requested` int(10) unsigned NOT NULL,
@ -35,26 +43,11 @@ CREATE TABLE `oauth_sessions` (
KEY `client_id` (`client_id`) KEY `client_id` (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'scopes' CREATE TABLE `oauth_scopes` (
CREATE TABLE `scopes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`scope` varchar(255) NOT NULL DEFAULT '', `scope` varchar(255) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
`description` varchar(255) DEFAULT '', `description` varchar(255) DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `scope` (`scope`) UNIQUE KEY `scope` (`scope`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'oauth_session_scopes'
CREATE TABLE `oauth_session_scopes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(11) unsigned NOT NULL,
`access_token` varchar(40) NOT NULL DEFAULT '',
`scope` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `session_id` (`session_id`),
KEY `access_token` (`access_token`),
KEY `scope` (`scope`),
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
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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

@ -0,0 +1,408 @@
<?php
/**
* OAuth 2.0 Authentication Server
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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;
/**
* OAuth 2.0 authentication server class
*/
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 = ',';
/**
* The TTL (time to live) of an access token in seconds (default: 3600)
* @var integer
*/
static protected $expiresIn = 3600;
/**
* The registered grant response types
* @var array
*/
protected $responseTypes = array();
/**
* The client, scope and session storage classes
* @var array
*/
static protected $storages = array();
/**
* The registered grant types
* @var array
*/
static protected $grantTypes = array();
/**
* The request object
* @var Util\RequestInterface
*/
static protected $request = null;
/**
* Exception error codes
* @var array
*/
protected static $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.',
);
/**
* Get an exception message
*
* @param string $error The error message key
* @return string The error message
*/
public static function getExceptionMessage($error = '')
{
return self::$exceptionMessages[$error];
}
/**
* Get an exception code
*
* @param integer $code The exception code
* @return string The exception code type
*/
public static function getExceptionType($code = 0)
{
return self::$exceptionCodes[$code];
}
/**
* Create a new OAuth2 authentication server
*
* @param ClientInterface $client A class which inherits from Storage/ClientInterface
* @param SessionInterface $session A class which inherits from Storage/SessionInterface
* @param ScopeInterface $scope A class which inherits from Storage/ScopeInterface
*/
public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope)
{
self::$storages = array(
'client' => $client,
'session' => $session,
'scope' => $scope
);
}
/**
* Enable support for a grant
* @param GrantTypeInterface $grantType A grant class which conforms to Interface/GrantTypeInterface
* @param null|string $identifier An identifier for the grant (autodetected if not passed)
*/
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();
}
}
/**
* Check if a grant type has been enabled
* @param string $identifier The grant type identifier
* @return boolean Returns "true" if enabled, "false" if not
*/
public static function hasGrantType($identifier)
{
return (array_key_exists($identifier, self::$grantTypes));
}
/**
* Get the scope delimeter
*
* @return string The scope delimiter (default: ",")
*/
public function getScopeDelimeter()
{
return $this->scopeDelimeter;
}
/**
* Set the scope delimiter
*
* @param string $scopeDelimeter
*/
public function setScopeDelimeter($scopeDelimeter)
{
$this->scopeDelimeter = $scopeDelimeter;
}
/**
* Get the TTL for an access token
* @return int The TTL
*/
public static function getExpiresIn()
{
return self::$expiresIn;
}
/**
* Set the TTL for an access token
* @param int $expiresIn The new TTL
*/
public function setExpiresIn($expiresIn)
{
self::$expiresIn = $expiresIn;
}
/**
* Sets the Request Object
*
* @param Util\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 Util\RequestInterface
*/
public static function getRequest()
{
if (self::$request === null) {
// @codeCoverageIgnoreStart
self::$request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return self::$request;
}
/**
* Return a storage class
* @param string $obj The class required
* @return Storage\ClientInterface|Storage\ScopeInterface|Storage\SessionInterface
*/
public static function getStorage($obj)
{
return self::$storages[$obj];
}
/**
* Check authorise parameters
*
* @param array $inputParams Optional array of parsed $_GET keys
* @throws \OAuth2\Exception\ClientException
* @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 $authParams 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
*
* @param array $inputParams Optional array of parsed $_POST keys
* @return array Authorise request parameters
*/
public function issueAccessToken($inputParams = array())
{
$grantType = (isset($inputParams['grant_type'])) ?
$inputParams['grant_type'] :
self::getRequest()->post('grant_type');
if (is_null($grantType)) {
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($grantType, array_keys(self::$grantTypes))) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $grantType), 7);
}
// Complete the flow
return $this->getGrantType($grantType)->completeFlow($inputParams);
}
/**
* Return a grant type class
* @param string $grantType The grant type identifer
* @return class
*/
protected function getGrantType($grantType)
{
return self::$grantTypes[$grantType];
}
/**
* Get a parameter from passed input parameters or the Request class
* @param string|array $param Requried parameter
* @param string $method Get/put/post/delete
* @param array $inputParams Passed input parameters
* @return mixed 'Null' if parameter is missing
*/
public static function getParam($param = '', $method = 'get', $inputParams = array())
{
if (is_string($param)) {
return (isset($inputParams[$param])) ? $inputParams['client_id'] : self::getRequest()->{$method}($param);
} else {
$response = array();
foreach ($param as $p) {
$response[$p] = self::getParam($p, $method, $inputParams);
}
return $response;
}
}
}

View File

@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Client Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* ClientException Exception
*/
class ClientException extends OAuth2Exception
{
}

View File

@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Invalid Access Token Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* InvalidAccessToken Exception
*/
class InvalidAccessTokenException extends OAuth2Exception
{
}

View File

@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Invalid Grant Type Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* InvalidGrantTypeException Exception
*/
class InvalidGrantTypeException extends OAuth2Exception
{
}

View File

@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Base Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* Exception class
*/
class OAuth2Exception extends \Exception
{
}

View File

@ -0,0 +1,132 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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;
/**
* Auth code grant class
*/
class AuthCode implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'authorization_code';
/**
* Response type
* @var string
*/
protected $responseType = 'code';
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the auth code grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'redirect_uri', 'code'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
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;
// Validate the authorization 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,121 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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;
/**
* Client credentials grant class
*/
class ClientCredentials implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'client_credentials';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the client credentials grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and client secret
$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,54 @@
<?php
/**
* OAuth 2.0 Grant type interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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
* @return array An array of parameters to be passed back to the client
*/
public function completeFlow($inputParams = null);
}

View File

@ -0,0 +1,164 @@
<?php
/**
* OAuth 2.0 Password grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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;
/**
* Password grant class
*/
class Password implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'password';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Callback to authenticate a user's name and password
* @var function
*/
protected $callback = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Set the callback to verify a user's username and password
* @param function $callback The callback function
*/
public function setVerifyCredentialsCallback($callback)
{
$this->callback = $callback;
}
/**
* Return the callback function
* @return function
*/
protected function getVerifyCredentialsCallback()
{
if (is_null($this->callback) || ! is_callable($this->callback)) {
throw new Exception\InvalidGrantTypeException('Null or non-callable callback set');
}
return $this->callback;
}
/**
* Complete the password grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'username', 'password'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
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;
if (is_null($authParams['username'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'username'), 0);
}
if (is_null($authParams['password'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'password'), 0);
}
// Check if user's username and password are correct
$userId = call_user_func($this->getVerifyCredentialsCallback(), $authParams['username'], $authParams['password']);
if ($userId === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_credentials'), 0);
}
// 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'], 'user', $userId);
// Create a new session
AuthServer::getStorage('session')->createSession(
$authParams['client_id'],
null,
'user',
$userId,
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,116 @@
<?php
/**
* OAuth 2.0 Refresh token grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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;
/**
* Referesh token grant
*/
class RefreshToken implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'refresh_token';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the refresh token grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and client secret
$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;
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,232 @@
<?php
/**
* OAuth 2.0 Resource Server
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2;
use OutOfBoundsException;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\SessionScopeInterface;
use OAuth2\Util\RequestInterface;
use OAuth2\Util\Request;
/**
* OAuth 2.0 Resource Server
*/
class ResourceServer
{
/**
* The access token
* @var string
*/
protected $accessToken = null;
/**
* The session ID
* @var string
*/
protected $sessionId = null;
/**
* The type of the owner of the access token
* @var string
*/
protected $ownerType = null;
/**
* The ID of the owner of the access token
* @var string
*/
protected $ownerId = null;
/**
* The scopes associated with the access token
* @var array
*/
protected $sessionScopes = array();
/**
* The client, scope and session storage classes
* @var array
*/
protected $storages = array();
/**
* The request object
* @var Util\RequestInterface
*/
protected $request = null;
/**
* The query string key which is used by clients to present the access token (default: access_token)
* @var string
*/
protected $tokenKey = 'access_token';
/**
* Sets up the Resource
*
* @param SessionInterface The Session 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 Util\RequestInterface
*/
public function getRequest()
{
if ($this->request === null) {
// @codeCoverageIgnoreStart
$this->request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return $this->request;
}
/**
* Returns the query string key for the access token.
*
* @return string
*/
public function getTokenKey()
{
return $this->tokenKey;
}
/**
* Sets the query string key for the access token.
*
* @param $key The new query string key
*/
public function setTokenKey($key)
{
$this->tokenKey = $key;
}
/**
* Gets the access token owner ID.
*
* @return string
*/
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.
*
* @throws Exception\InvalidAccessTokenException Thrown if the presented access token is not valid
* @return bool
*/
public function isValid()
{
$access_token = $this->determineAccessToken();
$result = $this->storages['session']->validateAccessToken($access_token);
if ( ! $result) {
throw new Exception\InvalidAccessTokenException('Access token is not valid');
}
$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 presented access token has the given scope(s).
*
* @param array|string An array of scopes or a single scope as a string
* @return bool Returns bool if all scopes are found, false if any fail
*/
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.
*
* @throws Exception\MissingAccessTokenException Thrown if there is no access token presented
* @return string
*/
protected function determineAccessToken()
{
if ($header = $this->getRequest()->header('Authorization')) {
$access_token = base64_decode(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\InvalidAccessTokenException('Access token is missing');
}
return $access_token;
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* OAuth 2.0 Client storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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,41 @@
<?php
/**
* OAuth 2.0 Scope storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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,22 @@
<?php <?php
/**
* OAuth 2.0 Session storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
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,
@ -61,17 +25,18 @@ interface Database
* $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW())) * $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW()))
* </code> * </code>
* *
* @param string $clientId The client ID * @param string $clientId The client ID
* @param string $redirectUri The redirect URI * @param string $redirectUri The redirect URI
* @param string $type The session owner's type (default = "user") * @param string $type The session owner's type (default = "user")
* @param string $typeId The session owner's ID (default = "null") * @param string $typeId The session owner's ID (default = "null")
* @param string $authCode The authorisation code (default = "null") * @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null") * @param string $accessToken The access token (default = "null")
* @param string $refreshToken The refresh token (default = "null") * @param string $refreshToken The refresh token (default = "null")
* @param string $stage The stage of the session (default ="request") * @param int $accessTokenExpire The expiry time of an access token as a unix timestamp
* @return int The session ID * @param string $stage The stage of the session (default ="request")
* @return int The session ID
*/ */
public function newSession( public function createSession(
$clientId, $clientId,
$redirectUri, $redirectUri,
$type = 'user', $type = 'user',
@ -86,7 +51,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 =
@ -94,11 +59,12 @@ interface Database
* id = $sessionId * id = $sessionId
* </code> * </code>
* *
* @param string $sessionId The session ID * @param string $sessionId The session ID
* @param string $authCode The authorisation code (default = "null") * @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null") * @param string $accessToken The access token (default = "null")
* @param string $refreshToken The refresh token (default = "null") * @param string $refreshToken The refresh token (default = "null")
* @param string $stage The stage of the session (default ="request") * @param int $accessTokenExpire The expiry time of an access token as a unix timestamp
* @param string $stage The stage of the session (default ="request")
* @return void * @return void
*/ */
public function updateSession( public function updateSession(
@ -129,31 +95,10 @@ interface Database
$typeId $typeId
); );
public function validateRefreshToken($refreshToken, $clientId);
/**
* Update the refresh token
*
* Database 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);
/** /**
* 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
@ -192,31 +137,34 @@ interface Database
); );
/** /**
* Return the session ID for a given session owner and client combination * Validate an access token
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientId * SELECT id, owner_id, owner_type FROM oauth_sessions WHERE access_token = $accessToken
* AND owner_type = $type AND owner_id = $typeId
* </code> * </code>
* *
* @param string $type The session owner's type * Response:
* @param string $typeId The session owner's ID *
* @param string $clientId The client ID * <code>
* @return string|null Return the session ID as an integer if * Array
* found otherwise returns false * (
* [id] => (int) The session ID
* [owner_type] => (string) The owner type
* [owner_id] => (string) The owner ID
* )
* </code>
*
* @param [type] $accessToken [description]
* @return [type] [description]
*/ */
public function hasSession( public function validateAccessToken($accessToken);
$type,
$typeId,
$clientId
);
/** /**
* Return the access token for a given session * Return the access token for a given session
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* SELECT access_token FROM oauth_sessions WHERE id = $sessionId * SELECT access_token FROM oauth_sessions WHERE id = $sessionId
@ -229,106 +177,52 @@ interface Database
public function getAccessToken($sessionId); public function getAccessToken($sessionId);
/** /**
* Removes an authorisation code associated with a session * Validate a refresh token
* * @param string $refreshToken The refresh token
* Database query: * @param string $clientId The client ID
* * @return int The session ID
* <code>
* UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return void
*/ */
public function removeAuthCode($sessionId); public function validateRefreshToken($refreshToken, $clientId);
/** /**
* Sets a sessions access token * Update the refresh token
* *
* Database query: * Example SQL query:
* *
* <code> * <code>
* UPDATE oauth_sessions SET access_token = $accessToken WHERE id = * UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token =
* $sessionId * $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE
* id = $sessionId
* </code> * </code>
* *
* @param int $sessionId The OAuth session ID * @param string $sessionId The session ID
* @param string $accessToken The access token * @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 * @return void
*/ */
public function setAccessToken( public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires);
$sessionId,
$accessToken
);
/** /**
* 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 $scopeId 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 +247,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,31 @@
<?php
/**
* OAuth 2.0 Redirect URI generator
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Util;
/**
* RedirectUri class
*/
class RedirectUri
{
/**
* Generate a new redirect uri
* @param string $uri The base URI
* @param array $params The query string parameters
* @param string $queryDelimeter The query string delimeter (default: "?")
* @return string The updated URI
*/
public static function make($uri, $params = array(), $queryDelimeter = '?')
{
$uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&';
return $uri.http_build_query($params);
}
}

100
src/OAuth2/Util/Request.php Normal file
View File

@ -0,0 +1,100 @@
<?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()
{
if (function_exists('getallheaders')) {
// @codeCoverageIgnoreStart
$headers = getallheaders();
} else {
// @codeCoverageIgnoreEnd
$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,40 @@
<?php
/**
* OAuth 2.0 Secure key generator
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Util;
/**
* SecureKey class
*/
class SecureKey
{
/**
* Generate a new unique code
* @param integer $len Length of the generated code
* @return string
*/
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,230 +0,0 @@
<?php
namespace OAuth2\Client;
use Guzzle\Service\Client as GuzzleClient;
class IDPException extends \Exception
{
protected $result;
public function __construct($result)
{
$this->result = $result;
$code = isset($result['code']) ? $result['code'] : 0;
if (isset($result['error'])) {
// OAuth 2.0 Draft 10 style
$message = $result['error'];
} elseif (isset($result['message'])) {
// cURL style
$message = $result['message'];
} else {
$message = 'Unknown Error.';
}
parent::__construct($message['message'], $message['code']);
}
public function getType()
{
if (isset($this->result['error'])) {
$message = $this->result['error'];
if (is_string($message)) {
// OAuth 2.0 Draft 10 style
return $message;
}
}
return 'Exception';
}
/**
* To make debugging easier.
*
* @returns
* The string representation of the error.
*/
public function __toString()
{
$str = $this->getType() . ': ';
if ($this->code != 0) {
$str .= $this->code . ': ';
}
return $str . $this->message;
}
}
abstract class IDP {
public $clientId = '';
public $clientSecret = '';
public $redirectUri = '';
public $name;
public $uidKey = 'uid';
public $scopes = array();
public $method = 'post';
public $scopeSeperator = ',';
public $responseType = 'json';
public function __construct($options)
{
foreach ($options as $option => $value) {
if (isset($this->{$option})) {
$this->{$option} = $value;
}
}
}
abstract public function urlAuthorize();
abstract public function urlAccessToken();
abstract public function urlUserDetails(\Oauth2\Client\Token\Access $token);
abstract public function userDetails($response, \Oauth2\Client\Token\Access $token);
public function authorize($options = array())
{
$state = md5(uniqid(rand(), TRUE));
setcookie($this->name.'_authorize_state', $state);
$params = array(
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUri,
'state' => $state,
'scope' => is_array($this->scope) ? implode($this->scopeSeperator, $this->scope) : $this->scope,
'response_type' => isset($options['response_type']) ? $options['response_type'] : 'code',
'approval_prompt' => 'force' // - google force-recheck
);
header('Location: ' . $this->urlAuthorize().'?'.http_build_query($params));
exit;
}
public function getAccessToken($code = NULL, $options = array())
{
if ($code === NULL) {
throw new \BadMethodCallException('Missing authorization code');
}
$params = array(
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'grant_type' => isset($options['grantType']) ? $options['grantType'] : 'authorization_code',
);
switch ($params['grant_type']) {
case 'authorization_code':
$params['code'] = $code;
$params['redirect_uri'] = isset($options['redirectUri']) ? $options['redirectUri'] : $this->redirectUri;
break;
case 'refresh_token':
$params['refresh_token'] = $code;
break;
}
try {
switch ($this->method) {
case 'get':
$client = new GuzzleClient($this->urlAccessToken() . '?' . http_build_query($params));
$request = $client->send();
$response = $request->getBody();
break;
case 'post':
$client = new GuzzleClient($this->urlAccessToken());
$request = $client->post(null, null, $params)->send();
$response = $request->getBody();
break;
}
}
catch (\Guzzle\Http\Exception\BadResponseException $e)
{
$raw_response = explode("\n", $e->getResponse());
$response = end($raw_response);
}
switch ($this->responseType) {
case 'json':
$result = json_decode($response, true);
break;
case 'string':
parse_str($response, $result);
break;
}
if (isset($result['error']) && ! empty($result['error'])) {
throw new \Oauth2\Client\IDPException($result);
}
switch ($params['grant_type']) {
case 'authorization_code':
return \Oauth2\Client\Token::factory('access', $result);
break;
case 'refresh_token':
return \Oauth2\Client\Token::factory('refresh', $result);
break;
}
}
public function getUserDetails(\Oauth2\Client\Token\Access $token)
{
$url = $this->urlUserDetails($token);
try {
$client = new GuzzleClient($url);
$request = $client->get()->send();
$response = $request->getBody();
return $this->userDetails(json_decode($response), $token);
}
catch (\Guzzle\Http\Exception\BadResponseException $e)
{
$raw_response = explode("\n", $e->getResponse());
throw new \Oauth2\Client\IDPException(end($raw_response));
}
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace OAuth2\Client;
class Provider
{
private function __constuct() {}
public static function factory($name, array $options = null)
{
if ( ! class_exists($name)) {
throw new OAuth2\Client\Exception('There is no identity provider called: '.$name);
}
return new $name($options);
}
}

View File

@ -1,42 +0,0 @@
<?php
class Blooie extends Oauth2\Client\IDP
{
public $scope = array('user.profile', 'user.picture');
public $method = 'POST';
public function urlAuthorize()
{
return 'https://bloo.ie/oauth';
}
public function urlAccessToken()
{
return 'https://bloo.ie/oauth/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token,
'urls' => array(
'Facebook' => $user->link,
),
);
}
}

View File

@ -1,49 +0,0 @@
<?php
/**
* Facebook OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class Facebook extends Oauth2\Client\IDP
{
protected $scope = array('offline_access', 'email', 'read_stream');
public function urlAuthorize()
{
return 'https://www.facebook.com/dialog/oauth';
}
public function urlAccessToken()
{
return 'https://graph.facebook.com/oauth/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => isset($user->username) ? $user->username : null,
'name' => $user->name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token,
'urls' => array(
'Facebook' => $user->link,
),
);
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Foursquare OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class Foursquare extends Oauth2\Client\IDP
{
public $method = 'POST';
public function urlAuthorize()
{
return 'https://foursquare.com/oauth2/authenticate';
}
public function urlAccessToken()
{
return 'https://foursquare.com/oauth2/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://api.foursquare.com/v2/users/self?'.http_build_query(array(
'oauth_token' => $token->access_token,
));
$response = json_decode(file_get_contents($url));
$user = $response->response->user;
// Create a response from the request
return array(
'uid' => $user->id,
'name' => sprintf('%s %s', $user->firstName, $user->lastName),
'email' => $user->contact->email,
'image' => $user->photo,
'location' => $user->homeCity,
);
}
}

View File

@ -1,43 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* GitHub OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Github extends Oauth2\Client\IDP
{
public function urlAuthorize()
{
return 'https://github.com/login/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://github.com/login/oauth/access_token';
}
public function getUserInfo(Oauth\Token\Access $token)
{
$url = 'https://api.github.com/user?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => $user->login,
'name' => $user->name,
'email' => $user->email,
'urls' => array(
'GitHub' => 'http://github.com/'.$user->login,
'Blog' => $user->blog,
),
);
}
}

View File

@ -1,84 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Google OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Google extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
public $method = 'POST';
/**
* @var string scope separator, most use "," but some like Google are spaces
*/
public $scope_seperator = ' ';
public function url_authorize()
{
return 'https://accounts.google.com/o/oauth2/auth';
}
public function url_access_token()
{
return 'https://accounts.google.com/o/oauth2/token';
}
public function __construct(array $options = array())
{
// Now make sure we have the default scope to get user data
empty($options['scope']) and $options['scope'] = array(
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'
);
// Array it if its string
$options['scope'] = (array) $options['scope'];
parent::__construct($options);
}
/*
* Get access to the API
*
* @param string The access code
* @return object Success or failure along with the response details
*/
public function access($code, $options = array())
{
if ($code === null)
{
throw new OAuth2_Exception(array('message' => 'Expected Authorization Code from '.ucfirst($this->name).' is missing'));
}
return parent::access($code, $options);
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url), true);
return array(
'uid' => $user['id'],
'nickname' => url_title($user['name'], '_', true),
'name' => $user['name'],
'first_name' => $user['given_name'],
'last_name' => $user['family_name'],
'email' => $user['email'],
'location' => null,
'image' => (isset($user['picture'])) ? $user['picture'] : null,
'description' => null,
'urls' => array(),
);
}
}

View File

@ -1,48 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Instagram OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Instagram extends OAuth2_Provider
{
/**
* @var string scope separator, most use "," but some like Google are spaces
*/
public $scope_seperator = '+';
/**
* @var string the method to use when requesting tokens
*/
public $method = 'POST';
public function url_authorize()
{
return 'https://api.instagram.com/oauth/authorize';
}
public function url_access_token()
{
return 'https://api.instagram.com/oauth/access_token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$user = $token->user;
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->full_name,
'image' => $user->profile_picture,
'urls' => array(
'website' => $user->website,
),
);
}
}

View File

@ -1,36 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Mailchimp OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Mailchimp extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://login.mailchimp.com/oauth2/authorize';
}
public function url_access_token()
{
return 'https://login.mailchimp.com/oauth2/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
// Create a response from the request
return array(
'uid' => $token->access_token,
);
}
}

View File

@ -1,73 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Mailru OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Mailru extends OAuth2_Provider
{
public $method = 'POST';
public function url_authorize()
{
return 'https://connect.mail.ru/oauth/authorize';
}
public function url_access_token()
{
return 'https://connect.mail.ru/oauth/token';
}
protected function sign_server_server(array $request_params, $secret_key)
{
ksort($request_params);
$params = '';
foreach ($request_params as $key => $value) {
$params .= "$key=$value";
}
return md5($params . $secret_key);
}
public function get_user_info(OAuth2_Token_Access $token)
{
$request_params = array(
'app_id' => $this->client_id,
'method' => 'users.getInfo',
'uids' => $token->uid,
'access_token' => $token->access_token,
'secure' => 1
);
$sig = $this->sign_server_server($request_params,$this->client_secret);
$url = 'http://www.appsmail.ru/platform/api?'.http_build_query($request_params).'&sig='.$sig;
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user[0]->uid,
'nickname' => $user[0]->nick,
'name' => $user[0]->first_name.' '.$user[0]->last_name,
'first_name' => $user[0]->first_name,
'last_name' => $user[0]->last_name,
'email' => isset($user[0]->email) ? $user[0]->email : null,
'image' => isset($user[0]->pic_big) ? $user[0]->pic_big : null,
);
}
public function authorize($options = array())
{
$state = md5(uniqid(rand(), TRUE));
get_instance()->session->set_userdata('state', $state);
$params = array(
'client_id' => $this->client_id,
'redirect_uri' => isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri,
'response_type' => 'code',
);
redirect($this->url_authorize().'?'.http_build_query($params));
}
}

View File

@ -1,59 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* PayPal OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Paypal extends OAuth2_Provider
{
/**
* @var string default scope (useful if a scope is required for user info)
*/
protected $scope = array('https://identity.x.com/xidentity/resources/profile/me');
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://identity.x.com/xidentity/resources/authorize';
}
public function url_access_token()
{
return 'https://identity.x.com/xidentity/oauthtokenservice';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://identity.x.com/xidentity/resources/profile/me?' . http_build_query(array(
'oauth_token' => $token->access_token
));
$user = json_decode(file_get_contents($url));
$user = $user->identity;
return array(
'uid' => $user['userId'],
'nickname' => url_title($user['fullName'], '_', true),
'name' => $user['fullName'],
'first_name' => $user['firstName'],
'last_name' => $user['lastName'],
'email' => $user['emails'][0],
'location' => $user->addresses[0],
'image' => null,
'description' => null,
'urls' => array(
'PayPal' => null
)
);
}
}

View File

@ -1,51 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Soundcloud OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Soundcloud extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://soundcloud.com/connect';
}
public function url_access_token()
{
return 'https://api.soundcloud.com/oauth2/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://api.soundcloud.com/me.json?'.http_build_query(array(
'oauth_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
// Create a response from the request
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->full_name,
'location' => $user->country.' ,'.$user->country,
'description' => $user->description,
'image' => $user->avatar_url,
'urls' => array(
'MySpace' => $user->myspace_name,
'Website' => $user->website,
),
);
}
}

View File

@ -1,54 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Vkontakte OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Vkontakte extends OAuth2_Provider
{
protected $method = 'POST';
public $uid_key = 'user_id';
public function url_authorize()
{
return 'http://oauth.vk.com/authorize';
}
public function url_access_token()
{
return 'https://oauth.vk.com/access_token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$scope = array('nickname', 'screen_name','photo_big');
$url = 'https://api.vk.com/method/users.get?'.http_build_query(array(
'uids' => $token->uid,
'fields' => implode(",",$scope),
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url))->response;
if(sizeof($user)==0)
return null;
else
$user = $user[0];
return array(
'uid' => $user->uid,
'nickname' => isset($user->nickname) ? $user->nickname : null,
'name' => isset($user->name) ? $user->name : null,
'first_name' => isset($user->first_name) ? $user->first_name : null,
'last_name' => isset($user->last_name) ? $user->last_name : null,
'email' => null,
'location' => null,
'description' => null,
'image' => isset($user->photo_big) ? $user->photo_big : null,
'urls' => array(),
);
}
}

View File

@ -1,60 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Windows Live OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Windowslive extends OAuth2_Provider
{
protected $scope = array('wl.basic', 'wl.emails');
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
// authorise url
public function url_authorize()
{
return 'https://oauth.live.com/authorize';
}
// access token url
public function url_access_token()
{
return 'https://oauth.live.com/token';
}
// get basic user information
/********************************
** this can be extended through the
** use of scopes, check out the document at
** http://msdn.microsoft.com/en-gb/library/hh243648.aspx#user
*********************************/
public function get_user_info(OAuth2_Token_Access $token)
{
// define the get user information token
$url = 'https://apis.live.net/v5.0/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
// perform network request
$user = json_decode(file_get_contents($url));
// create a response from the request and return it
return array(
'uid' => $user->id,
'name' => $user->name,
'nickname' => url_title($user->name, '_', true),
// 'location' => $user[''], # scope wl.postal_addresses is required
# but won't be implemented by default
'locale' => $user->locale,
'urls' => array('Windows Live' => $user->link),
);
}
}

View File

@ -1,115 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Yandex OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Yandex extends OAuth2_Provider
{
public $method = 'POST';
public function url_authorize()
{
return 'https://oauth.yandex.ru/authorize';
}
public function url_access_token()
{
return 'https://oauth.yandex.ru/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$opts = array(
'http' => array(
'method' => 'GET',
'header' => 'Authorization: OAuth '.$token->access_token
)
);
$_default_opts = stream_context_get_params(stream_context_get_default());
$opts = array_merge_recursive($_default_opts['options'], $opts);
$context = stream_context_create($opts);
$url = 'http://api-yaru.yandex.ru/me/?format=json';
$user = json_decode(file_get_contents($url,false,$context));
preg_match("/\d+$/",$user->id,$uid);
return array(
'uid' => $uid[0],
'nickname' => isset($user->name) ? $user->name : null,
'name' => isset($user->name) ? $user->name : null,
'first_name' => isset($user->first_name) ? $user->first_name : null,
'last_name' => isset($user->last_name) ? $user->last_name : null,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => $user->links->userpic,
);
}
public function access($code, $options = array())
{
$params = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => isset($options['grant_type']) ? $options['grant_type'] : 'authorization_code',
);
switch ($params['grant_type'])
{
case 'authorization_code':
$params['code'] = $code;
$params['redirect_uri'] = isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri;
break;
case 'refresh_token':
$params['refresh_token'] = $code;
break;
}
$response = null;
$url = $this->url_access_token();
$curl = curl_init($url);
$headers[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8;';
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
// curl_setopt($curl, CURLOPT_USERAGENT, 'yamolib-php');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_TIMEOUT, 80);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
// curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
// curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/../data/ca-certificate.crt');
$response = curl_exec($curl);
curl_close($curl);
$return = json_decode($response, true);
if ( ! empty($return['error']))
{
throw new OAuth2_Exception($return);
}
switch ($params['grant_type'])
{
case 'authorization_code':
return OAuth2_Token::factory('access', $return);
break;
case 'refresh_token':
return OAuth2_Token::factory('refresh', $return);
break;
}
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace Oauth2\Client;
abstract class Token
{
/**
* Create a new token object.
*
* @param string token type
* @param array token options
* @return Token
*/
public static function factory($name = 'access', array $options = null)
{
include_once 'Token/'.ucfirst(strtolower($name)).'.php';
$class = 'Oauth2\Client\Token\\'.ucfirst($name);
return new $class($options);
}
/**
* Return the value of any protected class variable.
*
* @param string variable name
* @return mixed
*/
public function __get($key)
{
return $this->$key;
}
/**
* Return a boolean if the property is set
*
* @param string variable name
* @return bool
*/
public function __isset($key)
{
return isset($this->$key);
}
} // End Token

View File

@ -1,79 +0,0 @@
<?php
namespace Oauth2\Client\Token;
/**
* OAuth2 Token
*
* @package OAuth2
* @category Token
* @author Phil Sturgeon
* @copyright (c) 2011 HappyNinjas Ltd
*/
class Access extends \Oauth2\Client\Token
{
/**
* @var string accessToken
*/
protected $accessToken;
/**
* @var int expires
*/
protected $expires;
/**
* @var string refreshToken
*/
protected $refreshToken;
/**
* @var string uid
*/
protected $uid;
/**
* Sets the token, expiry, etc values.
*
* @param array token options
* @return void
*/
public function __construct(array $options = null)
{
if ( ! isset($options['access_token'])) {
throw new \BadMethodCallException('Required option not passed: access_token'.PHP_EOL.print_r($options, true));
}
$this->accessToken = $options['access_token'];
// Some providers (not many) give the uid here, so lets take it
isset($options['uid']) and $this->uid = $options['uid'];
//Vkontakte uses user_id instead of uid
isset($options['user_id']) and $this->uid = $options['user_id'];
//Mailru uses x_mailru_vid instead of uid
isset($options['x_mailru_vid']) and $this->uid = $options['x_mailru_vid'];
// We need to know when the token expires, add num. seconds to current time
isset($options['expires_in']) and $this->expires = time() + ((int) $options['expires_in']);
// Facebook is just being a spec ignoring jerk
isset($options['expires']) and $this->expires = time() + ((int) $options['expires']);
// Grab a refresh token so we can update access tokens when they expires
isset($options['refresh_token']) and $this->refreshToken = $options['refresh_token'];
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->accessToken;
}
}

View File

@ -1,55 +0,0 @@
<?php
/**
* OAuth2 Token
*
* @package OAuth2
* @category Token
* @author Phil Sturgeon
* @copyright (c) 2011 HappyNinjas Ltd
*/
class Authorize extends \Oauth2\Client\Token
{
/**
* @var string code
*/
protected $code;
/**
* @var string redirect_uri
*/
protected $redirectUri;
/**
* Sets the token, expiry, etc values.
*
* @param array token options
* @return void
*/
public function __construct(array $options)
{
if ( ! isset($options['code'])) {
throw new Exception('Required option not passed: code');
} elseif ( ! isset($options['redirect_uri'])) {
throw new Exception('Required option not passed: redirect_uri');
}
$this->code = $options['code'];
$this->redirectUri = $options['redirect_uri'];
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->code;
}
}

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 = base64_decode(str_replace('Bearer ', '', trim($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,606 @@
<?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_getExceptionCode()
{
$this->assertEquals('access_denied', OAuth2\AuthServer::getExceptionType(2));
}
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 tearDown() {
M::close();
}
}

View File

@ -0,0 +1,189 @@
<?php
use \Mockery as m;
class Client_Credentials_Grant_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 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_missingClientPassword()
{
$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->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->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_clientCredentialsGrant_withRefreshToken()
{
$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());
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_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']);
}
}

View File

@ -0,0 +1,347 @@
<?php
use \Mockery as m;
class Password_Grant_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 OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_passwordGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_passwordGrant_missingClientPassword()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_passwordGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\InvalidGrantTypeException
*/
function test_issueAccessToken_passwordGrant_invalidCallback()
{
$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);
$testCredentials = null;
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_missingUsername()
{
$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);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_missingPassword()
{
$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);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_badCredentials()
{
$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);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
}
function test_issueAccessToken_passwordGrant_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);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
$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']);
}
function test_issueAccessToken_passwordGrant()
{
$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);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$_POST['grant_type'] = 'password';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['username'] = 'foo';
$_POST['password'] = 'bar';
$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']);
}
function test_issueAccessToken_passwordGrant_withRefreshToken()
{
$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);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'password';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['username'] = 'foo';
$_POST['password'] = 'bar';
$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']);
}
}

View File

@ -0,0 +1,233 @@
<?php
use \Mockery as m;
class Refresh_Token_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);
}
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']);
}
}

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,172 @@
<?php
use \Mockery as m;
class Resource_Server_test extends PHPUnit_Framework_TestCase
{
private $session;
public function setUp()
{
$this->session = M::mock('OAuth2\Storage\SessionInterface');
}
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('access_token', $s->getTokenKey());
}
public function test_setTokenKey()
{
$s = $this->returnDefault();
$s->setTokenKey('oauth_token');
$reflector = new ReflectionClass($s);
$requestProperty = $reflector->getProperty('tokenKey');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue($s);
$this->assertEquals('oauth_token', $v);
}
/**
* @expectedException OAuth2\Exception\InvalidAccessTokenException
*/
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()
{
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$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);
}
/**
* @expectedException OAuth2\Exception\InvalidAccessTokenException
*/
public function test_isValid_notValid()
{
$this->session->shouldReceive('validateAccessToken')->andReturn(false);
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$s = $this->returnDefault();
$s->setRequest($request);
$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'));
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$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));
}
}