Merge branch 'v4.0.0-relational-example' into v4.0.0-WIP

This commit is contained in:
Alex Bilbie
2014-08-06 09:02:54 +01:00
76 changed files with 1945 additions and 298 deletions

View File

@@ -14,6 +14,7 @@ namespace League\OAuth2\Server;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\TokenType\TokenTypeInterface;
use Symfony\Component\HttpFoundation\Request;
use League\Event\Emitter;
/**
* OAuth 2.0 Resource Server
@@ -40,6 +41,42 @@ abstract class AbstractServer
*/
protected $tokenType;
/**
* Event emitter
*/
protected $eventEmitter;
/**
* Abstract server constructor
*/
public function __construct()
{
$this->setEventEmitter();
}
/**
* Set an event emitter
* @param object $emitter Event emitter object
*/
public function setEventEmitter($emitter = null)
{
if ($emitter === null) {
$this->eventEmitter = new Emitter;
} else {
$this->eventEmitter = $emitter;
}
}
public function addEventListener($eventName, callable $listener)
{
$this->eventEmitter->addListener($eventName, $listener);
}
public function getEventEmitter()
{
return $this->eventEmitter;
}
/**
* Sets the Request Object
* @param \Symfony\Component\HttpFoundation\Request The Request Object
@@ -86,7 +123,7 @@ abstract class AbstractServer
* @param TokenTypeInterface $tokenType The token type
* @return void
*/
public function setTokenType(TokenTypeInterface $tokenType)
public function setIdType(TokenTypeInterface $tokenType)
{
$this->tokenType = $tokenType;
}

View File

@@ -78,7 +78,9 @@ class AuthorizationServer extends AbstractServer
$this->storages = [];
// Set Bearer as the default token type
$this->setTokenType(new Bearer);
$this->setIdType(new Bearer);
parent::__construct();
return $this;
}

View File

@@ -21,10 +21,10 @@ use Symfony\Component\HttpFoundation\ParameterBag;
abstract class AbstractTokenEntity
{
/**
* Access token ID
* Token identifier
* @var string
*/
protected $token;
protected $id;
/**
* Associated session
@@ -34,7 +34,7 @@ abstract class AbstractTokenEntity
/**
* Session scopes
* @var \Symfony\Component\HttpFoundation\ParameterBag
* @var array Array of ScopeEntity
*/
protected $scopes;
@@ -96,13 +96,13 @@ abstract class AbstractTokenEntity
}
/**
* Set access token ID
* Set token ID
* @param string $token Token ID
* @return self
*/
public function setToken($token = null)
public function setId($id = null)
{
$this->token = ($token !== null) ? $token : SecureKey::generate();
$this->id = ($id !== null) ? $id : SecureKey::generate();
return $this;
}
@@ -111,9 +111,9 @@ abstract class AbstractTokenEntity
* Get the token ID
* @return string
*/
public function getToken()
public function getId()
{
return $this->token;
return $this->id;
}
/**
@@ -153,11 +153,10 @@ abstract class AbstractTokenEntity
*/
public function __toString()
{
if (is_null($this->token)) {
throw new \BadMethodCallException('Token is null');
if ($this->id === null) {
return '';
}
return $this->token;
return $this->id;
}
/**

View File

@@ -66,7 +66,7 @@ class AccessTokenEntity extends AbstractTokenEntity
public function save()
{
$this->server->getStorage('access_token')->create(
$this->getToken(),
$this->getId(),
$this->getExpireTime(),
$this->getSession()->getId()
);

View File

@@ -55,7 +55,7 @@ class AuthCodeEntity extends AbstractTokenEntity
$uri .= (strstr($this->getRedirectUri(), $queryDelimeter) === false) ? $queryDelimeter : '&';
return $uri.http_build_query([
'code' => $this->getToken(),
'code' => $this->getId(),
'state' => $state
]);
}
@@ -94,9 +94,10 @@ class AuthCodeEntity extends AbstractTokenEntity
public function save()
{
$this->server->getStorage('auth_code')->create(
$this->getToken(),
$this->getId(),
$this->getExpireTime(),
$this->getSession()->getId()
$this->getSession()->getId(),
$this->getRedirectUri()
);
// Associate the scope with the token

View File

@@ -18,6 +18,8 @@ use League\OAuth2\Server\AbstractServer;
*/
class ClientEntity
{
use EntityTrait;
/**
* Client identifier
* @var string
@@ -60,18 +62,6 @@ class ClientEntity
return $this;
}
/**
* Set the client identifier
* @param string $id
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Return the client identifier
* @return string
@@ -81,18 +71,6 @@ class ClientEntity
return $this->id;
}
/**
* Set the client secret
* @param string $secret
* @return self
*/
public function setSecret($secret)
{
$this->secret = $secret;
return $this;
}
/**
* Return the client secret
* @return string
@@ -102,18 +80,6 @@ class ClientEntity
return $this->secret;
}
/**
* Set the client name
* @param string $name
* @return self
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get the client name
* @return string
@@ -123,18 +89,6 @@ class ClientEntity
return $this->name;
}
/**
* Set the client redirect URI
* @param string $redirectUri
* @return self
*/
public function setRedirectUri($redirectUri)
{
$this->redirectUri = $redirectUri;
return $this;
}
/**
* Returnt the client redirect URI
* @return string

View File

@@ -0,0 +1,30 @@
<?php
/**
* OAuth 2.0 Entity trait
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
trait EntityTrait
{
/**
* Hydrate an entity with properites
* @param array $properties
*/
public function hydrate(array $properties)
{
foreach ($properties as $prop => $val) {
if (property_exists($this, $prop)) {
$this->{$prop} = $val;
}
}
return $this;
}
}

View File

@@ -20,16 +20,34 @@ class RefreshTokenEntity extends AbstractTokenEntity
* Access token associated to refresh token
* @var \League\OAuth2\Server\Entity\AccessTokenEntity
*/
protected $accessToken;
protected $accessTokenEntity;
/**
* Id of the access token
* @var string
*/
protected $accessTokenId;
/**
* Set the ID of the associated access token
* @param string $accessToken
* @return self
*/
public function setAccessTokenId($accessTokenId)
{
$this->accessTokenId = $accessTokenId;
return $this;
}
/**
* Associate an access token
* @param \League\OAuth2\Server\Entity\AccessTokenEntity $accessToken
* @return self
*/
public function setAccessToken(AccessTokenEntity $accessToken)
public function setAccessToken(AccessTokenEntity $accessTokenEntity)
{
$this->accessToken = $accessToken;
$this->accessTokenEntity = $accessTokenEntity;
return $this;
}
@@ -40,11 +58,11 @@ class RefreshTokenEntity extends AbstractTokenEntity
*/
public function getAccessToken()
{
if (! $this->accessToken instanceof AccessTokenEntity) {
$this->accessToken = $this->server->getStorage('access_token')->getByRefreshToken($this);
if (! $this->accessTokenEntity instanceof AccessTokenEntity) {
$this->accessTokenEntity = $this->server->getStorage('access_token')->get($this->accessTokenId);
}
return $this->accessToken;
return $this->accessTokenEntity;
}
/**
@@ -53,9 +71,9 @@ class RefreshTokenEntity extends AbstractTokenEntity
public function save()
{
$this->server->getStorage('refresh_token')->create(
$this->getToken(),
$this->getId(),
$this->getExpireTime(),
$this->getAccessToken()->getToken()
$this->getAccessToken()->getId()
);
}

View File

@@ -18,6 +18,8 @@ use League\OAuth2\Server\AbstractServer;
*/
class ScopeEntity implements \JsonSerializable
{
use EntityTrait;
/**
* Scope identifier
* @var string
@@ -48,18 +50,6 @@ class ScopeEntity implements \JsonSerializable
return $this;
}
/**
* Set the scope identifer
* @param string $id The scope identifier
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Return the scope identifer
* @return string
@@ -69,18 +59,6 @@ class ScopeEntity implements \JsonSerializable
return $this->id;
}
/**
* Set the scope's descripton
* @param string $description
* @return self
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Return the scope's description
* @return string

View File

@@ -12,6 +12,7 @@
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
use League\OAuth2\Server\Event;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
@@ -228,6 +229,8 @@ class SessionEntity
$this->ownerType = $type;
$this->ownerId = $id;
$this->server->getEventEmitter()->emit(new Event\SessionOwnerEvent($this));
return $this;
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* OAuth 2.0 session owner event
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Event;
use League\Event\AbstractEvent;
use League\OAuth2\Server\Entity\SessionEntity;
class SessionOwnerEvent extends AbstractEvent
{
/**
* Session entity
* @var \League\OAuth2\Server\Entity\SessionEntity
*/
private $session;
/**
* Init the event with a session
* @param \League\OAuth2\Server\Entity\SessionEntity $session
*/
public function __construct(SessionEntity $session)
{
$this->session = $session;
}
/**
* The name of the event
* @return string
*/
public function getName()
{
return 'session.owner';
}
/**
* Return session
* @return \League\OAuth2\Server\Entity\SessionEntity
*/
public function getSession()
{
return $this->session;
}
}

View File

@@ -34,8 +34,7 @@ class InvalidGrantException extends OAuthException
{
parent::__construct(
sprintf(
'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.',
'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.',
$parameter
)
);

View File

@@ -19,12 +19,12 @@ class InvalidRefreshException extends OAuthException
/**
* {@inheritdoc}
*/
public $httpStatusCode = 401;
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_client';
public $errorType = 'invalid_request';
/**
* {@inheritdoc}

View File

@@ -34,8 +34,7 @@ class InvalidRequestException extends OAuthException
{
parent::__construct(
sprintf(
'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.',
'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.',
$parameter
)
);

View File

@@ -31,8 +31,7 @@ class ServerErrorException extends OAuthException
*/
public function __construct($parameter = null)
{
$parameter = is_null($parameter) ? 'The authorization server encountered an unexpected condition which prevented
it from fulfilling the request.' : $parameter;
$parameter = is_null($parameter) ? 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.' : $parameter;
parent::__construct($parameter);
}
}

View File

@@ -29,7 +29,7 @@ class UnauthorizedClientException extends OAuthException
/**
* {@inheritdoc}
*/
public function __construct($parameter)
public function __construct()
{
parent::__construct('The client is not authorized to request an access token using this method.');
}

View File

@@ -66,12 +66,11 @@ class AuthCodeGrant extends AbstractGrant
}
/**
* Check authorise parameters
* Check authorize parameters
*
* @throws
* @return array Authorise request parameters
* @return array Authorize request parameters
*/
public function checkAuthoriseParams()
public function checkAuthorizeParams()
{
// Get required params
$clientId = $this->server->getRequest()->query->get('client_id', null);
@@ -125,14 +124,14 @@ class AuthCodeGrant extends AbstractGrant
}
/**
* Parse a new authorise request
* Parse a new authorize 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
* @param array $authParams The authorize request $_GET parameters
* @return string An authorisation code
*/
public function newAuthoriseRequest($type, $typeId, $authParams = [])
public function newAuthorizeRequest($type, $typeId, $authParams = [])
{
// Create a new session
$session = new SessionEntity($this->server);
@@ -142,8 +141,9 @@ class AuthCodeGrant extends AbstractGrant
// Create a new auth code
$authCode = new AuthCodeEntity($this->server);
$authCode->setToken(SecureKey::generate());
$authCode->setId(SecureKey::generate());
$authCode->setRedirectUri($authParams['redirect_uri']);
$authCode->setExpireTime(time() + $this->authTokenTTL);
foreach ($authParams['scopes'] as $scope) {
$authCode->associateScope($scope);
@@ -157,10 +157,9 @@ class AuthCodeGrant extends AbstractGrant
/**
* Complete the auth code grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
public function completeFlow()
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', null);
@@ -207,7 +206,7 @@ class AuthCodeGrant extends AbstractGrant
throw new Exception\InvalidRequestException('code');
}
// Check redirect URI presented matches redirect URI originally used in authorise request
// Check redirect URI presented matches redirect URI originally used in authorize request
if ($code->getRedirectUri() !== $redirectUri) {
throw new Exception\InvalidRequestException('redirect_uri');
}
@@ -217,23 +216,22 @@ class AuthCodeGrant extends AbstractGrant
// Generate the access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setToken(SecureKey::generate());
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->server->getAccessTokenTTL() + time());
foreach ($authCodeScopes as $authCodeScope) {
$session->associateScope($authCodeScope);
}
$this->server->getTokenType()->set('access_token', $accessToken->getToken());
$this->server->getTokenType()->set('expires', $accessToken->getExpireTime());
$this->server->getTokenType()->set('access_token', $accessToken->getId());
$this->server->getTokenType()->set('expires_in', $this->server->getAccessTokenTTL());
// Associate a refresh token if set
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken = new RefreshTokenEntity($this->server);
$refreshToken->setToken(SecureKey::generate());
$refreshToken->setId(SecureKey::generate());
$refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
$this->server->getTokenType()->set('refresh_token', $refreshToken->getToken());
$this->server->getTokenType()->set('refresh_token', $refreshToken->getId());
}
// Expire the auth code

View File

@@ -93,7 +93,7 @@ class ClientCredentialsGrant extends AbstractGrant
// Generate an access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setToken(SecureKey::generate());
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->server->getAccessTokenTTL() + time());
// Associate scopes with the session and access token
@@ -107,8 +107,7 @@ class ClientCredentialsGrant extends AbstractGrant
$accessToken->setSession($session);
$accessToken->save($this->server->getStorage('access_token'));
$this->server->getTokenType()->set('access_token', $accessToken->getToken());
$this->server->getTokenType()->set('expires', $accessToken->getExpireTime());
$this->server->getTokenType()->set('access_token', $accessToken->getId());
$this->server->getTokenType()->set('expires_in', $this->server->getAccessTokenTTL());
return $this->server->getTokenType()->generateResponse();

View File

@@ -72,10 +72,9 @@ class PasswordGrant extends AbstractGrant
/**
* Complete the password grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
public function completeFlow()
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', null);
@@ -134,7 +133,7 @@ class PasswordGrant extends AbstractGrant
// Generate an access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setToken(SecureKey::generate());
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->server->getAccessTokenTTL() + time());
// Associate scopes with the session and access token
@@ -143,16 +142,15 @@ class PasswordGrant extends AbstractGrant
$session->associateScope($scope);
}
$this->server->getTokenType()->set('access_token', $accessToken->getToken());
$this->server->getTokenType()->set('expires', $accessToken->getExpireTime());
$this->server->getTokenType()->set('access_token', $accessToken->getId());
$this->server->getTokenType()->set('expires_in', $this->server->getAccessTokenTTL());
// Associate a refresh token if set
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken = new RefreshTokenEntity($this->server);
$refreshToken->setToken(SecureKey::generate());
$refreshToken->setId(SecureKey::generate());
$refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
$this->server->getTokenType()->set('refresh_token', $refreshToken->getToken());
$this->server->getTokenType()->set('refresh_token', $refreshToken->getId());
}
// Save everything

View File

@@ -125,7 +125,7 @@ class RefreshTokenGrant extends AbstractGrant
// Generate a new access token and assign it the correct sessions
$newAccessToken = new AccessTokenEntity($this->server);
$newAccessToken->setToken(SecureKey::generate());
$newAccessToken->setId(SecureKey::generate());
$newAccessToken->setExpireTime($this->server->getAccessTokenTTL() + time());
$newAccessToken->setSession($session);
@@ -137,8 +137,7 @@ class RefreshTokenGrant extends AbstractGrant
$oldAccessToken->expire($this->server->getStorage('access_token'));
$newAccessToken->save($this->server->getStorage('access_token'));
$this->server->getTokenType()->set('access_token', $newAccessToken->getToken());
$this->server->getTokenType()->set('expires', $newAccessToken->getExpireTime());
$this->server->getTokenType()->set('access_token', $newAccessToken->getId());
$this->server->getTokenType()->set('expires_in', $this->server->getAccessTokenTTL());
// Expire the old refresh token
@@ -146,12 +145,12 @@ class RefreshTokenGrant extends AbstractGrant
// Generate a new refresh token
$newRefreshToken = new RefreshTokenEntity($this->server);
$newRefreshToken->setToken(SecureKey::generate());
$newRefreshToken->setId(SecureKey::generate());
$newRefreshToken->setExpireTime($this->getRefreshTokenTTL() + time());
$newRefreshToken->setAccessToken($newAccessToken);
$newRefreshToken->save($this->server->getStorage('refresh_token'));
$this->server->getTokenType()->set('refresh_token', $newRefreshToken->getToken());
$this->server->getTokenType()->set('refresh_token', $newRefreshToken->getId());
return $this->server->getTokenType()->generateResponse();
}

View File

@@ -64,7 +64,9 @@ class ResourceServer extends AbstractServer
$this->setStorage('scope', $scopeStorage);
// Set Bearer as the default token type
$this->setTokenType(new Bearer);
$this->setIdType(new Bearer);
parent::__construct();
return $this;
}
@@ -87,7 +89,7 @@ class ResourceServer extends AbstractServer
* Returns the query string key for the access token.
* @return string
*/
public function getTokenKey()
public function getIdKey()
{
return $this->tokenKey;
}
@@ -97,7 +99,7 @@ class ResourceServer extends AbstractServer
* @param $key The new query string key
* @return self
*/
public function setTokenKey($key)
public function setIdKey($key)
{
$this->tokenKey = $key;
@@ -128,7 +130,7 @@ class ResourceServer extends AbstractServer
*/
public function getAccessToken()
{
return $this->accessToken->getToken();
return $this->accessToken->getId();
}
/**

View File

@@ -28,13 +28,6 @@ interface AccessTokenInterface
*/
public function get($token);
/**
* Get the access token associated with an access token
* @param \League\OAuth2\Server\Entity\RefreshTokenEntity $refreshToken
* @return \League\OAuth2\Server\Entity\AccessTokenEntity
*/
public function getByRefreshToken(RefreshTokenEntity $refreshToken);
/**
* Get the scopes for an access token
* @param \League\OAuth2\Server\Entity\AbstractTokenEntity $token The access token

View File

@@ -28,13 +28,14 @@ interface AuthCodeInterface
/**
* Create an auth code.
* @param string $token The token ID
* @param integer $expireTime Token expire time
* @param integer $sessionId Session identifier
* @param string $token The token ID
* @param integer $expireTime Token expire time
* @param integer $sessionId Session identifier
* @param string $redirectUri Client redirect uri
*
* @return void
*/
public function create($token, $expireTime, $sessionId);
public function create($token, $expireTime, $sessionId, $redirectUri);
/**
* Get the scopes for an access token

View File

@@ -21,13 +21,6 @@ use League\OAuth2\Server\Entity\ScopeEntity;
*/
interface SessionInterface
{
/**
* Get a session from it's identifier
* @param string $sessionId
* @return \League\OAuth2\Server\Entity\SessionEntity
*/
public function get($sessionId);
/**
* Get a session from an access token
* @param \League\OAuth2\Server\Entity\AccessTokenEntity $accessToken The access token

View File

@@ -23,7 +23,6 @@ class Bearer extends AbstractTokenType implements TokenTypeInterface
$return = [
'access_token' => $this->get('access_token'),
'token_type' => 'Bearer',
'expires' => $this->get('expires'),
'expires_in' => $this->get('expires_in')
];