First commit of AuthCode rewrite

This commit is contained in:
Alex Bilbie 2016-02-11 17:30:01 +00:00
parent 1e1043c04f
commit 92a101f263
3 changed files with 236 additions and 264 deletions

View File

@ -0,0 +1,60 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Slim\App;
use Slim\Http\Request;
use Slim\Http\Response;
include(__DIR__ . '/../vendor/autoload.php');
// Setup the authorization server
$server = new Server('file://' . __DIR__ . '/../private.key');
// Init our repositories
$userRepository = new UserRepository();
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$accessTokenRepository = new AccessTokenRepository();
$refreshTokenRepository = new RefreshTokenRepository();
// Enable the client credentials grant on the server
$passwordGrant = new PasswordGrant(
$userRepository,
$clientRepository,
$scopeRepository,
$accessTokenRepository,
$refreshTokenRepository
);
$server->enableGrantType($passwordGrant);
// App
$app = new App([Server::class => $server]);
$app->any('/authorise', function (Request $request, Response $response) {
if (strtoupper($request->getMethod()) === 'GET') {
$response = $response->withHeader('Set-Cookie', $authCodeGrant->storeOriginalRequestParams)
}
});
$app->post('/access_token', function (Request $request, Response $response) {
/** @var Server $server */
$server = $this->get(Server::class);
try {
return $server->respondToRequest($request);
} catch (OAuthServerException $e) {
return $e->generateHttpResponse();
} catch (\Exception $e) {
return $response->withStatus(500)->write($e->getMessage());
}
});
$app->run();

View File

@ -0,0 +1,79 @@
<?php
namespace League\OAuth2\Server\Entities;
class AuthorizationCodeRequestEntity
{
/**
* @var string
*/
private $clientId;
/**
* @var null|string
*/
private $redirectUri;
/**
* @var null|string
*/
private $scope;
/**
* @var null|string
*/
private $state;
/**
* @return string
*/
public function getClientId()
{
return $this->clientId;
}
/**
* @return null|string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* @return null|string
*/
public function getScope()
{
return $this->scope;
}
/**
* @return null|string
*/
public function getState()
{
return $this->state;
}
/**
* AuthorizationCodeRequestEntity constructor.
*
* @param string $clientId
* @param string|null $redirectUri
* @param string|null $scope
* @param string|null $state
*/
public function __construct($clientId, $redirectUri = null, $scope = null, $state = null)
{
$this->clientId = $clientId;
$this->redirectUri = $redirectUri;
$this->scope = $scope;
$this->state = $state;
}
public function __sleep()
{
return ['clientId', 'redirectUri', 'scope', 'state'];
}
}

View File

@ -1,303 +1,136 @@
<?php <?php
/**
* OAuth 2.0 Auth code grant
*
* @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\Grant; namespace League\OAuth2\Server\Grant;
use League\Event\Emitter;
use League\Event\Event;
use League\OAuth2\Server\Entities\AccessTokenEntity;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Exception\InvalidClientException;
use League\OAuth2\Server\Exception\InvalidRequestException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\TokenTypes\TokenTypeInterface;
use League\OAuth2\Server\Utils\SecureKey;
use Symfony\Component\HttpFoundation\Request;
use DateInterval; use DateInterval;
use DateTime;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Auth code grant class
*/
class AuthCodeGrant extends AbstractGrant class AuthCodeGrant extends AbstractGrant
{ {
/** /**
* @var \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface * @inheritdoc
*/ */
protected $authCodeRepository; public function respondToRequest(
ServerRequestInterface $request,
/** ResponseTypeInterface $responseType,
* @param \League\Event\Emitter $emitter DateInterval $tokenTTL,
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository $scopeDelimiter = ' '
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
*/
public function __construct(
Emitter $emitter,
ClientRepositoryInterface $clientRepository,
ScopeRepositoryInterface $scopeRepository,
AccessTokenRepositoryInterface $accessTokenRepository,
AuthCodeRepositoryInterface $authCodeRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository = null
) { ) {
$this->authCodeRepository = $authCodeRepository; if (
$this->refreshTokenRepository = $refreshTokenRepository; isset($request->getQueryParams()['response_type'])
parent::__construct($emitter, $clientRepository, $scopeRepository, $accessTokenRepository); && $request->getQueryParams()['response_type'] === 'code'
&& isset($request->getQueryParams()['client_id'])
) {
return $this->respondToAuthorizationRequest($request, $scopeDelimiter, $tokenTTL);
} elseif (
isset($request->getParsedBody()['grant_type'])
&& $request->getParsedBody()['grant_type'] === 'authorization_code'
) {
return $this->respondToAccessTokenRequest($request, $responseType, $tokenTTL);
} else {
throw OAuthServerException::serverError('respondToRequest() should not have been called');
}
} }
/** /**
* Grant identifier * Respond to an authorization request
* *
* @var string * @param \Psr\Http\Message\ServerRequestInterface $request
* @param string $scopeDelimiter
* @param DateTime $tokenTTL
*/ */
protected $identifier = 'authorization_code'; protected function respondToAuthorizationRequest(
ServerRequestInterface $request,
/** $scopeDelimiter = ' ',
* Response type DateTime $tokenTTL
* ) {
* @var string
*/
protected $responseType = 'code';
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
*/
protected $server = null;
/**
* Access token expires in override
*
* @var int
*/
protected $accessTokenTTL = null;
/**
* The TTL of the auth token
*
* @var integer
*/
protected $authTokenTTL = 600;
/**
* Override the default access token expire time
*
* @param int $authTokenTTL
*
* @return void
*/
public function setAuthTokenTTL($authTokenTTL)
{
$this->authTokenTTL = $authTokenTTL;
}
/**
* Check authorize parameters
*
* @return array Authorize request parameters
*
* @throws
*/
/*public function checkAuthorizeParams()
{
// Get required params // Get required params
$clientId = $request->query->get('client_id', null); /*$clientId = array_key_exists('client_id', $request->getQueryParams())
? $request->getQueryParams()['client_id'] // $_GET['client_id']
: null;
if (is_null($clientId)) { if (is_null($clientId)) {
throw new InvalidRequestException('client_id'); throw OAuthServerException::invalidRequest('client_id', null, '`%s` parameter is missing');
} }
$redirectUri = $request->query->get('redirect_uri', null); $redirectUri = array_key_exists('redirect_uri', $request->getQueryParams())
? $request->getQueryParams()['redirect_uri'] // $_GET['redirect_uri']
: null;
if (is_null($redirectUri)) { if (is_null($redirectUri)) {
throw new InvalidRequestException('redirect_uri'); throw OAuthServerException::invalidRequest('redirect_uri', null, '`%s` parameter is missing');
} }
// Validate client ID and redirect URI // Validate client ID and redirect URI
$client = $this->server->getClientStorage()->get( $client = $this->clientRepository->getClientEntity(
$clientId, $clientId,
$this->getIdentifier(),
null, null,
$redirectUri, $redirectUri
$this->getIdentifier()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($request));
throw new Exception\InvalidClientException();
}
$state = $request->query->get('state', null);
if ($this->server->stateParamRequired() === true && is_null($state)) {
throw new InvalidRequestException('state', $redirectUri);
}
$responseType = $request->query->get('response_type', null);
if (is_null($responseType)) {
throw new InvalidRequestException('response_type', $redirectUri);
}
// Ensure response type is one that is recognised
if (!in_array($responseType, $this->server->getResponseTypes())) {
throw new Exception\UnsupportedResponseTypeException($responseType, $redirectUri);
}
// Validate any scopes that are in the request
$scopeParam = $request->query->get('scope', '');
$scopes = $this->validateScopes($scopeParam, $client, $redirectUri);
return [
'client' => $client,
'redirect_uri' => $redirectUri,
'state' => $state,
'response_type' => $responseType,
'scopes' => $scopes
];
}*/
/**
* 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 authorize request $_GET parameters
*
* @return string An authorisation code
*/
/*public function newAuthorizeRequest($type, $typeId, $authParams = [])
{
// Create a new session
$session = new SessionEntity($this->server);
$session->setOwner($type, $typeId);
$session->associateClient($authParams['client']);
$session->save();
// Create a new auth code
$authCode = new AuthCodeEntity($this->server);
$authCode->setId(SecureKey::generate());
$authCode->setRedirectUri($authParams['redirect_uri']);
$authCode->setExpireTime(time() + $this->authTokenTTL);
foreach ($authParams['scopes'] as $scope) {
$authCode->associateScope($scope);
}
$authCode->setSession($session);
$authCode->save();
return $authCode->generateRedirectUri($authParams['state']);
}*/
/**
* Return an access token
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \League\OAuth2\Server\TokenTypes\TokenTypeInterface $tokenType
* @param \DateInterval $accessTokenTTL
* @param string $scopeDelimiter
*
* @return \League\OAuth2\Server\TokenTypes\TokenTypeInterface
* @throws \League\OAuth2\Server\Exception\InvalidClientException
* @throws \League\OAuth2\Server\Exception\InvalidGrantException
* @throws \League\OAuth2\Server\Exception\InvalidRequestException
*/
public function getAccessTokenAsType(
Request $request,
TokenTypeInterface $tokenType,
DateInterval $accessTokenTTL,
$scopeDelimiter = ' '
) {
// Get the required params
$clientId = $request->request->get('client_id', $request->getUser());
if (is_null($clientId)) {
throw new InvalidRequestException('client_id', '');
}
$clientSecret = $request->request->get('client_secret',
$request->getPassword());
if (is_null($clientSecret)) {
throw new InvalidRequestException('client_secret');
}
$redirectUri = $request->request->get('redirect_uri', null);
if (is_null($redirectUri)) {
throw new InvalidRequestException('redirect_uri');
}
// Validate client ID and client secret
$client = $this->clientRepository->get(
$clientId,
$clientSecret,
$redirectUri,
$this->getIdentifier()
); );
if (($client instanceof ClientEntityInterface) === false) { if (($client instanceof ClientEntityInterface) === false) {
$this->emitter->emit(new Event('client.authentication.failed', $request)); throw OAuthServerException::invalidClient();
throw new InvalidClientException();
} }
// Validate the auth code $state = array_key_exists('state', $request->getQueryParams())
$authCode = $request->request->get('code', null); ? $request->getQueryParams()['state'] // $_GET['state']
if (is_null($authCode)) { : null;
throw new InvalidRequestException('code');
}
$code = $this->authCodeRepository->get($authCode); // Validate any scopes that are in the request
if (($code instanceof AuthCodeEntityInterface) === false) { $scopeParam = array_key_exists('scope', $request->getQueryParams())
throw new InvalidRequestException('code'); ? $request->getQueryParams()['scope'] // $_GET['scope']
} : '';
$scopes = $this->validateScopes($scopeParam, $scopeDelimiter, $client);
// Ensure the auth code hasn't expired // Create a new authorization code
if ($code->isExpired() === true) { $authCode = new AuthCodeEntity();
throw new InvalidRequestException('code'); $authCode->setIdentifier(SecureKey::generate());
} $authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL));
$authCode->setClient($client);
$authCode->setUserIdentifier($userEntity->getIdentifier());
// Check redirect URI presented matches redirect URI originally used in authorize request // Associate scopes with the session and access token
if ($code->getRedirectUri() !== $redirectUri) { foreach ($scopes as $scope) {
throw new InvalidRequestException('redirect_uri'); $authCode->addScope($scope);
} }*/
}
// Generate the access token /**
$accessToken = new AccessTokenEntity($this->server); * Respond to an access token request
$accessToken->setIdentifier(SecureKey::generate()); *
$expirationDateTime = (new \DateTime())->add($accessTokenTTL); * @param \Psr\Http\Message\ServerRequestInterface $request
$accessToken->setExpiryDateTime($expirationDateTime); * @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
$accessToken->setClient($client); * @param \DateInterval $accessTokenTTL
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
protected function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
DateInterval $accessTokenTTL
) {
foreach ($code->getScopes() as $scope) { }
$accessToken->addScope($scope);
}
$tokenType->setAccessToken($accessToken); /**
* @inheritdoc
// Associate a refresh token if set */
if ($this->refreshTokenRepository instanceof RefreshTokenRepositoryInterface) { public function canRespondToRequest(ServerRequestInterface $request)
// $refreshToken = new RefreshTokenEntity($this->server); {
// $refreshToken->setId(SecureKey::generate()); return (
// $refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time()); (
// $tokenType->setParam('refresh_token', $refreshToken->getId()); strtoupper($request->getMethod()) === 'GET'
// $refreshToken->setAccessToken($accessToken); && isset($request->getQueryParams()['response_type'])
} && $request->getQueryParams()['response_type'] === 'code'
&& isset($request->getQueryParams()['client_id'])
// Expire the auth code ) || (
$this->authCodeRepository->delete($code); isset($request->getParsedBody()['grant_type'])
&& $request->getParsedBody()['grant_type'] === 'authorization_code'
// Save the access token )
$this->accessTokenRepository->create($accessToken); );
return $tokenType;
} }
} }