diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index fd5cb52f..3734f91a 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -11,10 +11,13 @@ namespace League\OAuth2\Server\Grant; -use League\OAuth2\Server\AuthorizationServer; -use League\OAuth2\Server\Entity\ClientEntity; -use League\OAuth2\Server\Entity\ScopeEntity; +use League\Event\Emitter; +use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface; +use League\OAuth2\Server\Entities\ScopeEntity; use League\OAuth2\Server\Exception; +use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; +use League\OAuth2\Server\Repositories\ClientRepositoryInterface; +use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; /** * Abstract grant class @@ -29,32 +32,54 @@ abstract class AbstractGrant implements GrantTypeInterface protected $identifier = ''; /** - * Response type + * Grant responds with * * @var string */ - protected $responseType; + protected $respondsWith = 'token'; /** - * Callback to authenticate a user's name and password - * - * @var callable + * @var \Symfony\Component\HttpFoundation\Request */ - protected $callback; + protected $request; /** - * AuthServer instance - * - * @var \League\OAuth2\Server\AuthorizationServer + * @var ClientRepositoryInterface */ - protected $server; + protected $clientRepository; /** - * Access token expires in override - * - * @var int + * @var AccessTokenRepositoryInterface */ - protected $accessTokenTTL; + protected $accessTokenRepository; + + /** + * @var \League\Event\Emitter + */ + protected $emitter; + + /** + * @var ScopeRepositoryInterface + */ + protected $scopeRepository; + + /** + * @param \League\Event\Emitter $emitter + * @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository + * @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository + * @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository + */ + public function __construct( + Emitter $emitter, + ClientRepositoryInterface $clientRepository, + ScopeRepositoryInterface $scopeRepository, + AccessTokenRepositoryInterface $accessTokenRepository + ) { + $this->emitter = $emitter; + $this->clientRepository = $clientRepository; + $this->scopeRepository = $scopeRepository; + $this->accessTokenRepository = $accessTokenRepository; + } /** * {@inheritdoc} @@ -67,74 +92,27 @@ abstract class AbstractGrant implements GrantTypeInterface /** * {@inheritdoc} */ - public function setIdentifier($identifier) + public function respondsWith() { - $this->identifier = $identifier; - - return $this; + return $this->respondsWith; } /** - * {@inheritdoc} + * @param string $scopeParamValue A string containing a delimited set of scope identifiers + * @param string $scopeDelimiter The delimiter between the scopes in the value string + * @param ClientEntityInterface $client + * @param string $redirectUri + * + * @return \League\OAuth2\Server\Entities\ScopeEntity[] + * @throws \League\OAuth2\Server\Exception\InvalidScopeException */ - public function getResponseType() - { - return $this->responseType; - } - - /** - * Get the TTL for an access token - * - * @return int The TTL - */ - public function getAccessTokenTTL() - { - if ($this->accessTokenTTL) { - return $this->accessTokenTTL; - } - - return $this->server->getAccessTokenTTL(); - } - - /** - * Override the default access token expire time - * - * @param int $accessTokenTTL - * - * @return self - */ - public function setAccessTokenTTL($accessTokenTTL) - { - $this->accessTokenTTL = $accessTokenTTL; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAuthorizationServer(AuthorizationServer $server) - { - $this->server = $server; - - return $this; - } - - /** - * Given a list of scopes, validate them and return an array of Scope entities - * - * @param string $scopeParam A string of scopes (e.g. "profile email birthday") - * @param \League\OAuth2\Server\Entity\ClientEntity $client Client entity - * @param string|null $redirectUri The redirect URI to return the user to - * - * @return \League\OAuth2\Server\Entity\ScopeEntity[] - * - * @throws \League\OAuth2\Server\Exception\InvalidScopeException If scope is invalid, or no scopes passed when required - * @throws - */ - public function validateScopes($scopeParam = '', ClientEntity $client, $redirectUri = null) - { - $scopesList = explode($this->server->getScopeDelimiter(), $scopeParam); + public function validateScopes( + $scopeParamValue, + $scopeDelimiter, + ClientEntityInterface $client, + $redirectUri = null + ) { + $scopesList = explode($scopeDelimiter, trim($scopeParamValue)); for ($i = 0; $i < count($scopesList); $i++) { $scopesList[$i] = trim($scopesList[$i]); @@ -143,53 +121,19 @@ abstract class AbstractGrant implements GrantTypeInterface } } - if ( - $this->server->scopeParamRequired() === true - && $this->server->getDefaultScope() === null - && count($scopesList) === 0 - ) { - throw new Exception\InvalidRequestException('scope'); - } elseif (count($scopesList) === 0 && $this->server->getDefaultScope() !== null) { - if (is_array($this->server->getDefaultScope())) { - $scopesList = $this->server->getDefaultScope(); - } else { - $scopesList = [0 => $this->server->getDefaultScope()]; - } - } - $scopes = []; - foreach ($scopesList as $scopeItem) { - $scope = $this->server->getScopeStorage()->get( + $scope = $this->scopeRepository->get( $scopeItem, $this->getIdentifier(), - $client->getId() + $client->getIdentifier() ); if (($scope instanceof ScopeEntity) === false) { throw new Exception\InvalidScopeException($scopeItem, $redirectUri); } - $scopes[$scope->getId()] = $scope; - } - - return $scopes; - } - - /** - * Format the local scopes array - * - * @param \League\OAuth2\Server\Entity\ScopeEntity[] - * - * @return array - */ - protected function formatScopes($unformated = []) - { - $scopes = []; - foreach ($unformated as $scope) { - if ($scope instanceof ScopeEntity) { - $scopes[$scope->getId()] = $scope; - } + $scopes[] = $scope; } return $scopes; diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php index e219c633..f875143d 100644 --- a/src/Grant/ClientCredentialsGrant.php +++ b/src/Grant/ClientCredentialsGrant.php @@ -11,12 +11,14 @@ namespace League\OAuth2\Server\Grant; -use League\OAuth2\Server\Entity\AccessTokenEntity; -use League\OAuth2\Server\Entity\ClientEntity; -use League\OAuth2\Server\Entity\SessionEntity; -use League\OAuth2\Server\Event; +use DateInterval; +use League\Event\Event; +use League\OAuth2\Server\Entities\AccessTokenEntity; +use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface; use League\OAuth2\Server\Exception; -use League\OAuth2\Server\Util\SecureKey; +use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; +use League\OAuth2\Server\Utils\SecureKey; +use Symfony\Component\HttpFoundation\Request; /** * Client credentials grant class @@ -31,92 +33,70 @@ class ClientCredentialsGrant extends AbstractGrant protected $identifier = 'client_credentials'; /** - * Response type + * Return an access token * - * @var string + * @param \Symfony\Component\HttpFoundation\Request $request + * @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType + * @param \DateInterval $accessTokenTTL + * @param string $scopeDelimiter + * + * @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface + * @throws \League\OAuth2\Server\Exception\InvalidClientException + * @throws \League\OAuth2\Server\Exception\InvalidRequestException + * @throws \League\OAuth2\Server\Exception\InvalidScopeException */ - protected $responseType = null; - - /** - * AuthServer instance - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server = null; - - /** - * Access token expires in override - * - * @var int - */ - protected $accessTokenTTL = null; - - /** - * Complete the client credentials grant - * - * @return array - * - * @throws - */ - public function completeFlow() - { + public function getAccessTokenAsType( + Request $request, + ResponseTypeInterface $responseType, + DateInterval $accessTokenTTL, + $scopeDelimiter = ' ' + ) { // Get the required params - $clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser()); + $clientId = $request->request->get('client_id', $request->getUser()); if (is_null($clientId)) { throw new Exception\InvalidRequestException('client_id'); } - $clientSecret = $this->server->getRequest()->request->get('client_secret', - $this->server->getRequest()->getPassword()); + $clientSecret = $request->request->get('client_secret', $request->getPassword()); if (is_null($clientSecret)) { throw new Exception\InvalidRequestException('client_secret'); } // Validate client ID and client secret - $client = $this->server->getClientStorage()->get( + $client = $this->clientRepository->get( $clientId, $clientSecret, null, $this->getIdentifier() ); - if (($client instanceof ClientEntity) === false) { - $this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest())); + if (($client instanceof ClientEntityInterface) === false) { + $this->emitter->emit(new Event('client.authentication.failed', $request)); throw new Exception\InvalidClientException(); } // Validate any scopes that are in the request - $scopeParam = $this->server->getRequest()->request->get('scope', ''); - $scopes = $this->validateScopes($scopeParam, $client); - - // Create a new session - $session = new SessionEntity($this->server); - $session->setOwner('client', $client->getId()); - $session->associateClient($client); + $scopeParam = $request->request->get('scope', ''); + $scopes = $this->validateScopes($scopeParam, $scopeDelimiter, $client); // Generate an access token - $accessToken = new AccessTokenEntity($this->server); - $accessToken->setId(SecureKey::generate()); - $accessToken->setExpireTime($this->getAccessTokenTTL() + time()); + $accessToken = new AccessTokenEntity(); + $accessToken->setIdentifier(SecureKey::generate()); + $accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL)); + $accessToken->setClient($client); + $accessToken->setOwner('client', $client->getIdentifier()); // Associate scopes with the session and access token foreach ($scopes as $scope) { - $session->associateScope($scope); + $accessToken->addScope($scope); } - foreach ($session->getScopes() as $scope) { - $accessToken->associateScope($scope); - } + // Save the token + $this->accessTokenRepository->create($accessToken); - // Save everything - $session->save(); - $accessToken->setSession($session); - $accessToken->save(); + // Inject access token into token type + $responseType->setAccessToken($accessToken); - $this->server->getTokenType()->setSession($session); - $this->server->getTokenType()->setParam('access_token', $accessToken->getId()); - $this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL()); - - return $this->server->getTokenType()->generateResponse(); + return $responseType; } }