From 819da34cf120a2fc18c6d50a8218f794f78b4273 Mon Sep 17 00:00:00 2001 From: fengyuexingzi Date: Mon, 30 Oct 2017 17:39:29 +0800 Subject: [PATCH] 'curl_psot' --- composer.json | 5 +- examples/public/api.php | 2 +- examples/public/client_credentials.php | 2 +- examples/public/curl.php | 47 ++ examples/public/index.php | 17 +- examples/public/private.key | 27 + kauth/src/King.php | 19 + kauth/src/Tree/Tree.php | 18 + src/AuthorizationServer.php | 207 ------- .../AuthorizationValidatorInterface.php | 25 - .../BearerTokenValidator.php | 99 ---- src/CryptKey.php | 116 ---- src/CryptTrait.php | 64 --- src/Entities/AccessTokenEntityInterface.php | 24 - src/Entities/AuthCodeEntityInterface.php | 23 - src/Entities/ClientEntityInterface.php | 36 -- src/Entities/RefreshTokenEntityInterface.php | 55 -- src/Entities/ScopeEntityInterface.php | 20 - src/Entities/TokenInterface.php | 83 --- src/Entities/Traits/AccessTokenTrait.php | 61 --- src/Entities/Traits/AuthCodeTrait.php | 34 -- src/Entities/Traits/ClientTrait.php | 46 -- src/Entities/Traits/EntityTrait.php | 34 -- src/Entities/Traits/RefreshTokenTrait.php | 61 --- src/Entities/Traits/TokenEntityTrait.php | 116 ---- src/Entities/UserEntityInterface.php | 20 - src/Exception/OAuthServerException.php | 296 ---------- ...IdentifierConstraintViolationException.php | 20 - src/Grant/AbstractAuthorizeGrant.php | 29 - src/Grant/AbstractGrant.php | 512 ------------------ src/Grant/AuthCodeGrant.php | 354 ------------ src/Grant/ClientCredentialsGrant.php | 53 -- src/Grant/GrantTypeInterface.php | 135 ----- src/Grant/ImplicitGrant.php | 225 -------- src/Grant/PasswordGrant.php | 111 ---- src/Grant/RefreshTokenGrant.php | 133 ----- .../AuthorizationServerMiddleware.php | 55 -- src/Middleware/ResourceServerMiddleware.php | 55 -- .../AccessTokenRepositoryInterface.php | 57 -- .../AuthCodeRepositoryInterface.php | 51 -- .../ClientRepositoryInterface.php | 31 -- .../RefreshTokenRepositoryInterface.php | 51 -- src/Repositories/RepositoryInterface.php | 17 - src/Repositories/ScopeRepositoryInterface.php | 46 -- src/Repositories/UserRepositoryInterface.php | 33 -- src/RequestEvent.php | 46 -- src/RequestTypes/AuthorizationRequest.php | 224 -------- src/ResourceServer.php | 84 --- src/ResponseTypes/AbstractResponseType.php | 64 --- src/ResponseTypes/BearerTokenResponse.php | 78 --- src/ResponseTypes/RedirectResponse.php | 40 -- src/ResponseTypes/ResponseTypeInterface.php | 43 -- 52 files changed, 132 insertions(+), 3972 deletions(-) create mode 100644 examples/public/curl.php create mode 100644 examples/public/private.key create mode 100644 kauth/src/King.php create mode 100644 kauth/src/Tree/Tree.php delete mode 100644 src/AuthorizationServer.php delete mode 100644 src/AuthorizationValidators/AuthorizationValidatorInterface.php delete mode 100644 src/AuthorizationValidators/BearerTokenValidator.php delete mode 100644 src/CryptKey.php delete mode 100644 src/CryptTrait.php delete mode 100644 src/Entities/AccessTokenEntityInterface.php delete mode 100644 src/Entities/AuthCodeEntityInterface.php delete mode 100644 src/Entities/ClientEntityInterface.php delete mode 100644 src/Entities/RefreshTokenEntityInterface.php delete mode 100644 src/Entities/ScopeEntityInterface.php delete mode 100644 src/Entities/TokenInterface.php delete mode 100644 src/Entities/Traits/AccessTokenTrait.php delete mode 100644 src/Entities/Traits/AuthCodeTrait.php delete mode 100644 src/Entities/Traits/ClientTrait.php delete mode 100644 src/Entities/Traits/EntityTrait.php delete mode 100644 src/Entities/Traits/RefreshTokenTrait.php delete mode 100644 src/Entities/Traits/TokenEntityTrait.php delete mode 100644 src/Entities/UserEntityInterface.php delete mode 100644 src/Exception/OAuthServerException.php delete mode 100644 src/Exception/UniqueTokenIdentifierConstraintViolationException.php delete mode 100644 src/Grant/AbstractAuthorizeGrant.php delete mode 100644 src/Grant/AbstractGrant.php delete mode 100644 src/Grant/AuthCodeGrant.php delete mode 100644 src/Grant/ClientCredentialsGrant.php delete mode 100644 src/Grant/GrantTypeInterface.php delete mode 100644 src/Grant/ImplicitGrant.php delete mode 100644 src/Grant/PasswordGrant.php delete mode 100644 src/Grant/RefreshTokenGrant.php delete mode 100644 src/Middleware/AuthorizationServerMiddleware.php delete mode 100644 src/Middleware/ResourceServerMiddleware.php delete mode 100644 src/Repositories/AccessTokenRepositoryInterface.php delete mode 100644 src/Repositories/AuthCodeRepositoryInterface.php delete mode 100644 src/Repositories/ClientRepositoryInterface.php delete mode 100644 src/Repositories/RefreshTokenRepositoryInterface.php delete mode 100644 src/Repositories/RepositoryInterface.php delete mode 100644 src/Repositories/ScopeRepositoryInterface.php delete mode 100644 src/Repositories/UserRepositoryInterface.php delete mode 100644 src/RequestEvent.php delete mode 100644 src/RequestTypes/AuthorizationRequest.php delete mode 100644 src/ResourceServer.php delete mode 100644 src/ResponseTypes/AbstractResponseType.php delete mode 100644 src/ResponseTypes/BearerTokenResponse.php delete mode 100644 src/ResponseTypes/RedirectResponse.php delete mode 100644 src/ResponseTypes/ResponseTypeInterface.php diff --git a/composer.json b/composer.json index 49e88df..e1132f4 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,9 @@ "zendframework/zend-diactoros": "^1.0" }, "autoload": { - "psr-4": { - "League\\OAuth2\\Server\\": "src/" + "psr-4":{ + "KAuth\\":"kauth/src/", + "OAuth2ServerExamples\\":"examples/src/" } }, "autoload-dev": { diff --git a/examples/public/api.php b/examples/public/api.php index 3032ffe..2f35b27 100644 --- a/examples/public/api.php +++ b/examples/public/api.php @@ -27,7 +27,7 @@ $app->add( ) ); -// An example endpoint secured with OAuth 2.0 +// An example endpoint secured with kauth 2.0 $app->get( '/users', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) { diff --git a/examples/public/client_credentials.php b/examples/public/client_credentials.php index b036f80..71f89bd 100644 --- a/examples/public/client_credentials.php +++ b/examples/public/client_credentials.php @@ -17,7 +17,7 @@ use Psr\Http\Message\ServerRequestInterface; use Slim\App; use Zend\Diactoros\Stream; -include __DIR__ . '/../vendor/autoload.php'; +include __DIR__ . '/../../vendor/autoload.php'; $app = new App([ 'settings' => [ diff --git a/examples/public/curl.php b/examples/public/curl.php new file mode 100644 index 0000000..b012dd4 --- /dev/null +++ b/examples/public/curl.php @@ -0,0 +1,47 @@ + "client_credentials", + "client_id" => "myawesomeapp", + "client_secret" => "abc123", + "scope" => "basic email" + ]; + $data = http_build_query($data); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/x-www-form-urlencoded', + 'Accept: 1.0' + ]); + + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + + $result = curl_exec($ch); + + + if ($result === false) { + echo 'curlError: ' . curl_error($ch); + } else { + echo $result; + } + curl_close($ch); +} + +curl_post(); \ No newline at end of file diff --git a/examples/public/index.php b/examples/public/index.php index 71853e4..10a5bd5 100644 --- a/examples/public/index.php +++ b/examples/public/index.php @@ -5,4 +5,19 @@ * Date: 2017/10/28 * Time: 11:45 */ -echo 'index'; \ No newline at end of file + +use KAuth\Tree\Tree; + +include __DIR__ . '/../../vendor/autoload.php'; + + +var_dump(file_get_contents('php://input')); +die; + +$tree = new Tree(); +$tree->index(); + +var_dump(file_get_contents( __DIR__ . '/../private.key')); + +$keyPathPerms = decoct(fileperms(__DIR__ . '/../private.key') & 0777); +var_dump($keyPathPerms); \ No newline at end of file diff --git a/examples/public/private.key b/examples/public/private.key new file mode 100644 index 0000000..142fd6c --- /dev/null +++ b/examples/public/private.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxHSx2v6sdLIBYIGyDo68YXh2okin6R6Abt8PVMNAr/8+wCLX +JibPFR930d9wmu7NxKR2uXC7HmsFe5mgU8Y+EeziuW+1a5pNY77cB/z8j02dxZam +KW/U+mI4t/j4iGveM4fWsxx6fAYIhF60Wtj/fcNPrncCPcfKHW7fJhuth6ExwLgl +sN/LwVGHstP/KUY/F+nUX3l7Tj25FNaV1+I5bB5Rfi1Kp1udvVYSIhFIvgZdND9Y +JCT4u5HfbS7JohL4qkFVLuaILW+T7QWx68fZlJ115sDFzr0eno5OwzwRw6aqmB0C +Ukr2BmW/8EgUA5HU9MMfSPnbBBxsjCu3gWL+FwIDAQABAoIBAQCe/EVXEhUkl03P ++QXNDCxdwSxY5u2kFgAgObphgWYfSDRTL57oDC44TPAd03KAn9O8WNCQADAeTMPy +JACA64Ud4pQVN9cdDpGksDfG6zDFFC4jUmiETjGQs95s3DrdxFXdZAgXiWuCZSuN +XEse3k/dSit46GzS7JWfvjMu1uVXRWxQiRmke18tHqNJ+KA8hhF05olMGEA6oLwG +bu1pUL01iS+6UfVa1Oi7z8zGqTXpGKY6hHRjXQEZXH1oA6CaogTlUvtGUzRSYKeP +Ya1xVuF6gQDRrMKeZe9Vzyk2/uXgIP3aJS0NjPwXPnj3Ni6FtyjX+MV4Jomvb5FR +RgBOOIURAoGBAOBMFsWq4rvwDDZ8F/+qifYkzOOrXmM10Xq0XqULokEOGlZjRGhE +nHl23atGvHfXWWQayP705ZsW4MDxzLhtkCeCxgRWWsNDaEBY+Eq6QLZNPfoQ8KqU +40BZYxMmxereweQ2e5GPa6FQe0AcBnC8jOgQcMjdV5OvLhZ5g9LMb6YvAoGBAOA5 +M1jN8vc6Lr2AJBtPsRxobc2Q6moB0aqc0/+a+N+ZeahO6RkoGragMsRq57U1SFUR +oUEiJoUZzpVFul21fYFEym3m395agNZNioFks0P1lwFMXc+JLpXEjRKGSCD7K4lD +dn7Mhp2eXP2PRBYWsJkfLoU8c6NMGf2871Ai4xSZAoGADQ9hJBFXMmo/y8xd+V0M +u3BZHciUrmIr2GE4QZPz1qXjkrQk/40/LzNkpNxxjOjVI6cLnQzVcbpbS+DIctSu +WB6dORNuJYB/SX/ktTUzH2pP+YeS+9u/f7e0tSDE1XAzCf7CIy+erL3q70iyd04D +Rl/usUNyHf9NR7G7o0KUHbECgYEAjjUZEMCF0TDQhhVoUP4JCUheI5s+YP9IV9nh +RuKl50Jye0GY6wCZeKw/pn1a+X2So4lr6WBcZ9xHPjscCOTbdYoIjQ15fI+P2NsS +9h/E5lwzanphoQeTSR+AjXgm9Ov337WuyJq04fCXb6VWfF/lnye8nHoLqUzRyzDx +4rRNqzkCgYARGIA5qZMfDX1ogTGQZ1ghF3vRiPpRkEdNgoAOEfV9kAC8f55a8t6i +8sKM/vUVAj8bvV1W/xUaVMKEh06wI5z4uBUj5R+8wuWNKSrCv6TG/Znq62A/AGwe +hUlY+Em75lKV7Yn2ZbW6VT05l3zV/sIQhm5Xld98JFCqxCmkx08WXw== +-----END RSA PRIVATE KEY----- diff --git a/kauth/src/King.php b/kauth/src/King.php new file mode 100644 index 0000000..1a427b7 --- /dev/null +++ b/kauth/src/King.php @@ -0,0 +1,19 @@ + - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server; - -use League\Event\EmitterAwareInterface; -use League\Event\EmitterAwareTrait; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Grant\GrantTypeInterface; -use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; -use League\OAuth2\Server\Repositories\ClientRepositoryInterface; -use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; -use League\OAuth2\Server\RequestTypes\AuthorizationRequest; -use League\OAuth2\Server\ResponseTypes\BearerTokenResponse; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; - -class AuthorizationServer implements EmitterAwareInterface -{ - use EmitterAwareTrait; - - /** - * @var GrantTypeInterface[] - */ - protected $enabledGrantTypes = []; - - /** - * @var \DateInterval[] - */ - protected $grantTypeAccessTokenTTL = []; - - /** - * @var CryptKey - */ - protected $privateKey; - - /** - * @var CryptKey - */ - protected $publicKey; - - /** - * @var null|ResponseTypeInterface - */ - protected $responseType; - - /** - * @var ClientRepositoryInterface - */ - private $clientRepository; - - /** - * @var AccessTokenRepositoryInterface - */ - private $accessTokenRepository; - - /** - * @var ScopeRepositoryInterface - */ - private $scopeRepository; - - /** - * @var string - */ - private $encryptionKey; - - /** - * New server instance. - * - * @param ClientRepositoryInterface $clientRepository - * @param AccessTokenRepositoryInterface $accessTokenRepository - * @param ScopeRepositoryInterface $scopeRepository - * @param CryptKey|string $privateKey - * @param string $encryptionKey - * @param null|ResponseTypeInterface $responseType - */ - public function __construct( - ClientRepositoryInterface $clientRepository, - AccessTokenRepositoryInterface $accessTokenRepository, - ScopeRepositoryInterface $scopeRepository, - $privateKey, - $encryptionKey, - ResponseTypeInterface $responseType = null - ) { - $this->clientRepository = $clientRepository; - $this->accessTokenRepository = $accessTokenRepository; - $this->scopeRepository = $scopeRepository; - - if ($privateKey instanceof CryptKey === false) { - $privateKey = new CryptKey($privateKey); - } - $this->privateKey = $privateKey; - - $this->encryptionKey = $encryptionKey; - $this->responseType = $responseType; - } - - /** - * Enable a grant type on the server. - * - * @param GrantTypeInterface $grantType - * @param null|\DateInterval $accessTokenTTL - */ - public function enableGrantType(GrantTypeInterface $grantType, \DateInterval $accessTokenTTL = null) - { - if ($accessTokenTTL instanceof \DateInterval === false) { - $accessTokenTTL = new \DateInterval('PT1H'); - } - - $grantType->setAccessTokenRepository($this->accessTokenRepository); - $grantType->setClientRepository($this->clientRepository); - $grantType->setScopeRepository($this->scopeRepository); - $grantType->setPrivateKey($this->privateKey); - $grantType->setEmitter($this->getEmitter()); - $grantType->setEncryptionKey($this->encryptionKey); - - $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType; - $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL; - } - - /** - * Validate an authorization request - * - * @param ServerRequestInterface $request - * - * @throws OAuthServerException - * - * @return AuthorizationRequest - */ - public function validateAuthorizationRequest(ServerRequestInterface $request) - { - foreach ($this->enabledGrantTypes as $grantType) { - if ($grantType->canRespondToAuthorizationRequest($request)) { - return $grantType->validateAuthorizationRequest($request); - } - } - - throw OAuthServerException::unsupportedGrantType(); - } - - /** - * Complete an authorization request - * - * @param AuthorizationRequest $authRequest - * @param ResponseInterface $response - * - * @return ResponseInterface - */ - public function completeAuthorizationRequest(AuthorizationRequest $authRequest, ResponseInterface $response) - { - return $this->enabledGrantTypes[$authRequest->getGrantTypeId()] - ->completeAuthorizationRequest($authRequest) - ->generateHttpResponse($response); - } - - /** - * Return an access token response. - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * - * @throws OAuthServerException - * - * @return ResponseInterface - */ - public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response) - { - foreach ($this->enabledGrantTypes as $grantType) { - if ($grantType->canRespondToAccessTokenRequest($request)) { - $tokenResponse = $grantType->respondToAccessTokenRequest( - $request, - $this->getResponseType(), - $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] - ); - - if ($tokenResponse instanceof ResponseTypeInterface) { - return $tokenResponse->generateHttpResponse($response); - } - } - } - - throw OAuthServerException::unsupportedGrantType(); - } - - /** - * Get the token type that grants will return in the HTTP response. - * - * @return ResponseTypeInterface - */ - protected function getResponseType() - { - if ($this->responseType instanceof ResponseTypeInterface === false) { - $this->responseType = new BearerTokenResponse(); - } - - $this->responseType->setPrivateKey($this->privateKey); - $this->responseType->setEncryptionKey($this->encryptionKey); - - return $this->responseType; - } -} diff --git a/src/AuthorizationValidators/AuthorizationValidatorInterface.php b/src/AuthorizationValidators/AuthorizationValidatorInterface.php deleted file mode 100644 index 7e49f84..0000000 --- a/src/AuthorizationValidators/AuthorizationValidatorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\AuthorizationValidators; - -use Psr\Http\Message\ServerRequestInterface; - -interface AuthorizationValidatorInterface -{ - /** - * Determine the access token in the authorization header and append OAUth properties to the request - * as attributes. - * - * @param ServerRequestInterface $request - * - * @return ServerRequestInterface - */ - public function validateAuthorization(ServerRequestInterface $request); -} diff --git a/src/AuthorizationValidators/BearerTokenValidator.php b/src/AuthorizationValidators/BearerTokenValidator.php deleted file mode 100644 index 6f299ce..0000000 --- a/src/AuthorizationValidators/BearerTokenValidator.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\AuthorizationValidators; - -use Lcobucci\JWT\Parser; -use Lcobucci\JWT\Signer\Rsa\Sha256; -use Lcobucci\JWT\ValidationData; -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\CryptTrait; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; -use Psr\Http\Message\ServerRequestInterface; - -class BearerTokenValidator implements AuthorizationValidatorInterface -{ - use CryptTrait; - - /** - * @var AccessTokenRepositoryInterface - */ - private $accessTokenRepository; - - /** - * @var \League\OAuth2\Server\CryptKey - */ - protected $publicKey; - - /** - * @param AccessTokenRepositoryInterface $accessTokenRepository - */ - public function __construct(AccessTokenRepositoryInterface $accessTokenRepository) - { - $this->accessTokenRepository = $accessTokenRepository; - } - - /** - * Set the public key - * - * @param \League\OAuth2\Server\CryptKey $key - */ - public function setPublicKey(CryptKey $key) - { - $this->publicKey = $key; - } - - /** - * {@inheritdoc} - */ - public function validateAuthorization(ServerRequestInterface $request) - { - if ($request->hasHeader('authorization') === false) { - throw OAuthServerException::accessDenied('Missing "Authorization" header'); - } - - $header = $request->getHeader('authorization'); - $jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header[0])); - - try { - // Attempt to parse and validate the JWT - $token = (new Parser())->parse($jwt); - if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) { - throw OAuthServerException::accessDenied('Access token could not be verified'); - } - - // Ensure access token hasn't expired - $data = new ValidationData(); - $data->setCurrentTime(time()); - - if ($token->validate($data) === false) { - throw OAuthServerException::accessDenied('Access token is invalid'); - } - - // Check if token has been revoked - if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) { - throw OAuthServerException::accessDenied('Access token has been revoked'); - } - - // Return the request with additional attributes - return $request - ->withAttribute('oauth_access_token_id', $token->getClaim('jti')) - ->withAttribute('oauth_client_id', $token->getClaim('aud')) - ->withAttribute('oauth_user_id', $token->getClaim('sub')) - ->withAttribute('oauth_scopes', $token->getClaim('scopes')); - } catch (\InvalidArgumentException $exception) { - // JWT couldn't be parsed so return the request as is - throw OAuthServerException::accessDenied($exception->getMessage()); - } catch (\RuntimeException $exception) { - //JWR couldn't be parsed so return the request as is - throw OAuthServerException::accessDenied('Error while decoding to JSON'); - } - } -} diff --git a/src/CryptKey.php b/src/CryptKey.php deleted file mode 100644 index 2ede9e3..0000000 --- a/src/CryptKey.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server; - -class CryptKey -{ - const RSA_KEY_PATTERN = - '/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----\n)(.|\n)+(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)$/'; - - /** - * @var string - */ - protected $keyPath; - - /** - * @var null|string - */ - protected $passPhrase; - - /** - * @param string $keyPath - * @param null|string $passPhrase - * @param bool $keyPermissionsCheck - */ - public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true) - { - if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) { - $keyPath = $this->saveKeyToFile($keyPath); - } - - if (strpos($keyPath, 'file://') !== 0) { - $keyPath = 'file://' . $keyPath; - } - - if (!file_exists($keyPath) || !is_readable($keyPath)) { - throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath)); - } - - if ($keyPermissionsCheck === true) { - // Verify the permissions of the key - $keyPathPerms = decoct(fileperms($keyPath) & 0777); - if (in_array($keyPathPerms, ['600', '660'], true) === false) { - trigger_error(sprintf( - 'Key file "%s" permissions are not correct, should be 600 or 660 instead of %s', - $keyPath, - $keyPathPerms - ), E_USER_NOTICE); - } - } - - $this->keyPath = $keyPath; - $this->passPhrase = $passPhrase; - } - - /** - * @param string $key - * - * @throws \RuntimeException - * - * @return string - */ - private function saveKeyToFile($key) - { - $tmpDir = sys_get_temp_dir(); - $keyPath = $tmpDir . '/' . sha1($key) . '.key'; - - if (!file_exists($keyPath) && !touch($keyPath)) { - // @codeCoverageIgnoreStart - throw new \RuntimeException(sprintf('"%s" key file could not be created', $keyPath)); - // @codeCoverageIgnoreEnd - } - - if (file_put_contents($keyPath, $key) === false) { - // @codeCoverageIgnoreStart - throw new \RuntimeException(sprintf('Unable to write key file to temporary directory "%s"', $tmpDir)); - // @codeCoverageIgnoreEnd - } - - if (chmod($keyPath, 0600) === false) { - // @codeCoverageIgnoreStart - throw new \RuntimeException(sprintf('The key file "%s" file mode could not be changed with chmod to 600', $keyPath)); - // @codeCoverageIgnoreEnd - } - - return 'file://' . $keyPath; - } - - /** - * Retrieve key path. - * - * @return string - */ - public function getKeyPath() - { - return $this->keyPath; - } - - /** - * Retrieve key pass phrase. - * - * @return null|string - */ - public function getPassPhrase() - { - return $this->passPhrase; - } -} diff --git a/src/CryptTrait.php b/src/CryptTrait.php deleted file mode 100644 index 805969b..0000000 --- a/src/CryptTrait.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server; - -use Defuse\Crypto\Crypto; - -trait CryptTrait -{ - /** - * @var string - */ - protected $encryptionKey; - - /** - * Encrypt data with a private key. - * - * @param string $unencryptedData - * - * @throws \LogicException - * @return string - */ - protected function encrypt($unencryptedData) - { - try { - return Crypto::encryptWithPassword($unencryptedData, $this->encryptionKey); - } catch (\Exception $e) { - throw new \LogicException($e->getMessage()); - } - } - - /** - * Decrypt data with a public key. - * - * @param string $encryptedData - * - * @throws \LogicException - * @return string - */ - protected function decrypt($encryptedData) - { - try { - return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey); - } catch (\Exception $e) { - throw new \LogicException($e->getMessage()); - } - } - - /** - * Set the encryption key - * - * @param string $key - */ - public function setEncryptionKey($key = null) - { - $this->encryptionKey = $key; - } -} diff --git a/src/Entities/AccessTokenEntityInterface.php b/src/Entities/AccessTokenEntityInterface.php deleted file mode 100644 index c297e26..0000000 --- a/src/Entities/AccessTokenEntityInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -use League\OAuth2\Server\CryptKey; - -interface AccessTokenEntityInterface extends TokenInterface -{ - /** - * Generate a JWT from the access token - * - * @param CryptKey $privateKey - * - * @return string - */ - public function convertToJWT(CryptKey $privateKey); -} diff --git a/src/Entities/AuthCodeEntityInterface.php b/src/Entities/AuthCodeEntityInterface.php deleted file mode 100644 index e71aa2c..0000000 --- a/src/Entities/AuthCodeEntityInterface.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface AuthCodeEntityInterface extends TokenInterface -{ - /** - * @return string - */ - public function getRedirectUri(); - - /** - * @param string $uri - */ - public function setRedirectUri($uri); -} diff --git a/src/Entities/ClientEntityInterface.php b/src/Entities/ClientEntityInterface.php deleted file mode 100644 index 80cc70c..0000000 --- a/src/Entities/ClientEntityInterface.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface ClientEntityInterface -{ - /** - * Get the client's identifier. - * - * @return string - */ - public function getIdentifier(); - - /** - * Get the client's name. - * - * @return string - */ - public function getName(); - - /** - * Returns the registered redirect URI (as a string). - * - * Alternatively return an indexed array of redirect URIs. - * - * @return string|string[] - */ - public function getRedirectUri(); -} diff --git a/src/Entities/RefreshTokenEntityInterface.php b/src/Entities/RefreshTokenEntityInterface.php deleted file mode 100644 index 05e86e0..0000000 --- a/src/Entities/RefreshTokenEntityInterface.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface RefreshTokenEntityInterface -{ - /** - * Get the token's identifier. - * - * @return string - */ - public function getIdentifier(); - - /** - * Set the token's identifier. - * - * @param $identifier - */ - public function setIdentifier($identifier); - - /** - * Get the token's expiry date time. - * - * @return \DateTime - */ - public function getExpiryDateTime(); - - /** - * Set the date time when the token expires. - * - * @param \DateTime $dateTime - */ - public function setExpiryDateTime(\DateTime $dateTime); - - /** - * Set the access token that the refresh token was associated with. - * - * @param AccessTokenEntityInterface $accessToken - */ - public function setAccessToken(AccessTokenEntityInterface $accessToken); - - /** - * Get the access token that the refresh token was originally associated with. - * - * @return AccessTokenEntityInterface - */ - public function getAccessToken(); -} diff --git a/src/Entities/ScopeEntityInterface.php b/src/Entities/ScopeEntityInterface.php deleted file mode 100644 index 34ef75f..0000000 --- a/src/Entities/ScopeEntityInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface ScopeEntityInterface extends \JsonSerializable -{ - /** - * Get the scope's identifier. - * - * @return string - */ - public function getIdentifier(); -} diff --git a/src/Entities/TokenInterface.php b/src/Entities/TokenInterface.php deleted file mode 100644 index c842b09..0000000 --- a/src/Entities/TokenInterface.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface TokenInterface -{ - /** - * Get the token's identifier. - * - * @return string - */ - public function getIdentifier(); - - /** - * Set the token's identifier. - * - * @param $identifier - */ - public function setIdentifier($identifier); - - /** - * Get the token's expiry date time. - * - * @return \DateTime - */ - public function getExpiryDateTime(); - - /** - * Set the date time when the token expires. - * - * @param \DateTime $dateTime - */ - public function setExpiryDateTime(\DateTime $dateTime); - - /** - * Set the identifier of the user associated with the token. - * - * @param string|int $identifier The identifier of the user - */ - public function setUserIdentifier($identifier); - - /** - * Get the token user's identifier. - * - * @return string|int - */ - public function getUserIdentifier(); - - /** - * Get the client that the token was issued to. - * - * @return ClientEntityInterface - */ - public function getClient(); - - /** - * Set the client that the token was issued to. - * - * @param ClientEntityInterface $client - */ - public function setClient(ClientEntityInterface $client); - - /** - * Associate a scope with the token. - * - * @param ScopeEntityInterface $scope - */ - public function addScope(ScopeEntityInterface $scope); - - /** - * Return an array of scopes associated with the token. - * - * @return ScopeEntityInterface[] - */ - public function getScopes(); -} diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php deleted file mode 100644 index 741d6c1..0000000 --- a/src/Entities/Traits/AccessTokenTrait.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -use Lcobucci\JWT\Builder; -use Lcobucci\JWT\Signer\Key; -use Lcobucci\JWT\Signer\Rsa\Sha256; -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; - -trait AccessTokenTrait -{ - /** - * Generate a JWT from the access token - * - * @param CryptKey $privateKey - * - * @return string - */ - public function convertToJWT(CryptKey $privateKey) - { - return (new Builder()) - ->setAudience($this->getClient()->getIdentifier()) - ->setId($this->getIdentifier(), true) - ->setIssuedAt(time()) - ->setNotBefore(time()) - ->setExpiration($this->getExpiryDateTime()->getTimestamp()) - ->setSubject($this->getUserIdentifier()) - ->set('scopes', $this->getScopes()) - ->sign(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase())) - ->getToken(); - } - - /** - * @return ClientEntityInterface - */ - abstract public function getClient(); - - /** - * @return \DateTime - */ - abstract public function getExpiryDateTime(); - - /** - * @return string|int - */ - abstract public function getUserIdentifier(); - - /** - * @return ScopeEntityInterface[] - */ - abstract public function getScopes(); -} diff --git a/src/Entities/Traits/AuthCodeTrait.php b/src/Entities/Traits/AuthCodeTrait.php deleted file mode 100644 index 5bb9e30..0000000 --- a/src/Entities/Traits/AuthCodeTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -trait AuthCodeTrait -{ - /** - * @var null|string - */ - protected $redirectUri; - - /** - * @return string - */ - public function getRedirectUri() - { - return $this->redirectUri; - } - - /** - * @param string $uri - */ - public function setRedirectUri($uri) - { - $this->redirectUri = $uri; - } -} diff --git a/src/Entities/Traits/ClientTrait.php b/src/Entities/Traits/ClientTrait.php deleted file mode 100644 index fec76a6..0000000 --- a/src/Entities/Traits/ClientTrait.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -trait ClientTrait -{ - /** - * @var string - */ - protected $name; - - /** - * @var string|string[] - */ - protected $redirectUri; - - /** - * Get the client's name. - * - * @return string - * @codeCoverageIgnore - */ - public function getName() - { - return $this->name; - } - - /** - * Returns the registered redirect URI (as a string). - * - * Alternatively return an indexed array of redirect URIs. - * - * @return string|string[] - */ - public function getRedirectUri() - { - return $this->redirectUri; - } -} diff --git a/src/Entities/Traits/EntityTrait.php b/src/Entities/Traits/EntityTrait.php deleted file mode 100644 index 20c8659..0000000 --- a/src/Entities/Traits/EntityTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -trait EntityTrait -{ - /* - * @var string - */ - protected $identifier; - - /** - * @return mixed - */ - public function getIdentifier() - { - return $this->identifier; - } - - /** - * @param mixed $identifier - */ - public function setIdentifier($identifier) - { - $this->identifier = $identifier; - } -} diff --git a/src/Entities/Traits/RefreshTokenTrait.php b/src/Entities/Traits/RefreshTokenTrait.php deleted file mode 100644 index fb9dbc6..0000000 --- a/src/Entities/Traits/RefreshTokenTrait.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; - -trait RefreshTokenTrait -{ - /** - * @var AccessTokenEntityInterface - */ - protected $accessToken; - - /** - * @var \DateTime - */ - protected $expiryDateTime; - - /** - * {@inheritdoc} - */ - public function setAccessToken(AccessTokenEntityInterface $accessToken) - { - $this->accessToken = $accessToken; - } - - /** - * {@inheritdoc} - */ - public function getAccessToken() - { - return $this->accessToken; - } - - /** - * Get the token's expiry date time. - * - * @return \DateTime - */ - public function getExpiryDateTime() - { - return $this->expiryDateTime; - } - - /** - * Set the date time when the token expires. - * - * @param \DateTime $dateTime - */ - public function setExpiryDateTime(\DateTime $dateTime) - { - $this->expiryDateTime = $dateTime; - } -} diff --git a/src/Entities/Traits/TokenEntityTrait.php b/src/Entities/Traits/TokenEntityTrait.php deleted file mode 100644 index 0b5608c..0000000 --- a/src/Entities/Traits/TokenEntityTrait.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities\Traits; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; - -trait TokenEntityTrait -{ - /** - * @var ScopeEntityInterface[] - */ - protected $scopes = []; - - /** - * @var \DateTime - */ - protected $expiryDateTime; - - /** - * @var string|int - */ - protected $userIdentifier; - - /** - * @var ClientEntityInterface - */ - protected $client; - - /** - * Associate a scope with the token. - * - * @param ScopeEntityInterface $scope - */ - public function addScope(ScopeEntityInterface $scope) - { - $this->scopes[$scope->getIdentifier()] = $scope; - } - - /** - * Return an array of scopes associated with the token. - * - * @return ScopeEntityInterface[] - */ - public function getScopes() - { - return array_values($this->scopes); - } - - /** - * Get the token's expiry date time. - * - * @return \DateTime - */ - public function getExpiryDateTime() - { - return $this->expiryDateTime; - } - - /** - * Set the date time when the token expires. - * - * @param \DateTime $dateTime - */ - public function setExpiryDateTime(\DateTime $dateTime) - { - $this->expiryDateTime = $dateTime; - } - - /** - * Set the identifier of the user associated with the token. - * - * @param string|int $identifier The identifier of the user - */ - public function setUserIdentifier($identifier) - { - $this->userIdentifier = $identifier; - } - - /** - * Get the token user's identifier. - * - * @return string|int - */ - public function getUserIdentifier() - { - return $this->userIdentifier; - } - - /** - * Get the client that the token was issued to. - * - * @return ClientEntityInterface - */ - public function getClient() - { - return $this->client; - } - - /** - * Set the client that the token was issued to. - * - * @param ClientEntityInterface $client - */ - public function setClient(ClientEntityInterface $client) - { - $this->client = $client; - } -} diff --git a/src/Entities/UserEntityInterface.php b/src/Entities/UserEntityInterface.php deleted file mode 100644 index c71cb9c..0000000 --- a/src/Entities/UserEntityInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Entities; - -interface UserEntityInterface -{ - /** - * Return the user's identifier. - * - * @return mixed - */ - public function getIdentifier(); -} diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php deleted file mode 100644 index 45e03c0..0000000 --- a/src/Exception/OAuthServerException.php +++ /dev/null @@ -1,296 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Exception; - -use Psr\Http\Message\ResponseInterface; - -class OAuthServerException extends \Exception -{ - /** - * @var int - */ - private $httpStatusCode; - - /** - * @var string - */ - private $errorType; - - /** - * @var null|string - */ - private $hint; - - /** - * @var null|string - */ - private $redirectUri; - - /** - * Throw a new exception. - * - * @param string $message Error message - * @param int $code Error code - * @param string $errorType Error type - * @param int $httpStatusCode HTTP status code to send (default = 400) - * @param null|string $hint A helper hint - * @param null|string $redirectUri A HTTP URI to redirect the user back to - */ - public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null) - { - parent::__construct($message, $code); - $this->httpStatusCode = $httpStatusCode; - $this->errorType = $errorType; - $this->hint = $hint; - $this->redirectUri = $redirectUri; - } - - /** - * Unsupported grant type error. - * - * @return static - */ - public static function unsupportedGrantType() - { - $errorMessage = 'The authorization grant type is not supported by the authorization server.'; - $hint = 'Check the `grant_type` parameter'; - - return new static($errorMessage, 2, 'unsupported_grant_type', 400, $hint); - } - - /** - * Invalid request error. - * - * @param string $parameter The invalid parameter - * @param null|string $hint - * - * @return static - */ - public static function invalidRequest($parameter, $hint = null) - { - $errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' . - 'includes a parameter more than once, or is otherwise malformed.'; - $hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint; - - return new static($errorMessage, 3, 'invalid_request', 400, $hint); - } - - /** - * Invalid client error. - * - * @return static - */ - public static function invalidClient() - { - $errorMessage = 'Client authentication failed'; - - return new static($errorMessage, 4, 'invalid_client', 401); - } - - /** - * Invalid scope error. - * - * @param string $scope The bad scope - * @param null|string $redirectUri A HTTP URI to redirect the user back to - * - * @return static - */ - public static function invalidScope($scope, $redirectUri = null) - { - $errorMessage = 'The requested scope is invalid, unknown, or malformed'; - $hint = sprintf( - 'Check the `%s` scope', - htmlspecialchars($scope, ENT_QUOTES, 'UTF-8', false) - ); - - return new static($errorMessage, 5, 'invalid_scope', 400, $hint, $redirectUri); - } - - /** - * Invalid credentials error. - * - * @return static - */ - public static function invalidCredentials() - { - return new static('The user credentials were incorrect.', 6, 'invalid_credentials', 401); - } - - /** - * Server error. - * - * @param $hint - * - * @return static - * - * @codeCoverageIgnore - */ - public static function serverError($hint) - { - return new static( - 'The authorization server encountered an unexpected condition which prevented it from fulfilling' - . ' the request: ' . $hint, - 7, - 'server_error', - 500 - ); - } - - /** - * Invalid refresh token. - * - * @param null|string $hint - * - * @return static - */ - public static function invalidRefreshToken($hint = null) - { - return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint); - } - - /** - * Access denied. - * - * @param null|string $hint - * @param null|string $redirectUri - * - * @return static - */ - public static function accessDenied($hint = null, $redirectUri = null) - { - return new static( - 'The resource owner or authorization server denied the request.', - 9, - 'access_denied', - 401, - $hint, - $redirectUri - ); - } - - /** - * Invalid grant. - * - * @param string $hint - * - * @return static - */ - public static function invalidGrant($hint = '') - { - return new static( - 'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token ' - . 'is invalid, expired, revoked, does not match the redirection URI used in the authorization request, ' - . 'or was issued to another client.', - 10, - 'invalid_grant', - 400, - $hint - ); - } - - /** - * @return string - */ - public function getErrorType() - { - return $this->errorType; - } - - /** - * Generate a HTTP response. - * - * @param ResponseInterface $response - * @param bool $useFragment True if errors should be in the URI fragment instead of query string - * - * @return ResponseInterface - */ - public function generateHttpResponse(ResponseInterface $response, $useFragment = false) - { - $headers = $this->getHttpHeaders(); - - $payload = [ - 'error' => $this->getErrorType(), - 'message' => $this->getMessage(), - ]; - - if ($this->hint !== null) { - $payload['hint'] = $this->hint; - } - - if ($this->redirectUri !== null) { - if ($useFragment === true) { - $this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&'; - } else { - $this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&'; - } - - return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload)); - } - - foreach ($headers as $header => $content) { - $response = $response->withHeader($header, $content); - } - - $response->getBody()->write(json_encode($payload)); - - return $response->withStatus($this->getHttpStatusCode()); - } - - /** - * Get all headers that have to be send with the error response. - * - * @return array Array with header values - */ - public function getHttpHeaders() - { - $headers = [ - 'Content-type' => 'application/json', - ]; - - // Add "WWW-Authenticate" header - // - // RFC 6749, section 5.2.: - // "If the client attempted to authenticate via the 'Authorization' - // request header field, the authorization server MUST - // respond with an HTTP 401 (Unauthorized) status code and - // include the "WWW-Authenticate" response header field - // matching the authentication scheme used by the client. - // @codeCoverageIgnoreStart - if ($this->errorType === 'invalid_client') { - $authScheme = 'Basic'; - if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false - && strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0 - ) { - $authScheme = 'Bearer'; - } - $headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"'; - } - // @codeCoverageIgnoreEnd - return $headers; - } - - /** - * Returns the HTTP status code to send when the exceptions is output. - * - * @return int - */ - public function getHttpStatusCode() - { - return $this->httpStatusCode; - } - - /** - * @return null|string - */ - public function getHint() - { - return $this->hint; - } -} diff --git a/src/Exception/UniqueTokenIdentifierConstraintViolationException.php b/src/Exception/UniqueTokenIdentifierConstraintViolationException.php deleted file mode 100644 index a67855b..0000000 --- a/src/Exception/UniqueTokenIdentifierConstraintViolationException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Exception; - -class UniqueTokenIdentifierConstraintViolationException extends OAuthServerException -{ - public static function create() - { - $errorMessage = 'Could not create unique access token identifier'; - - return new static($errorMessage, 100, 'access_token_duplicate', 500); - } -} diff --git a/src/Grant/AbstractAuthorizeGrant.php b/src/Grant/AbstractAuthorizeGrant.php deleted file mode 100644 index 7f05100..0000000 --- a/src/Grant/AbstractAuthorizeGrant.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -abstract class AbstractAuthorizeGrant extends AbstractGrant -{ - /** - * @param string $uri - * @param array $params - * @param string $queryDelimiter - * - * @return string - */ - public function makeRedirectUri($uri, $params = [], $queryDelimiter = '?') - { - $uri .= (strstr($uri, $queryDelimiter) === false) ? $queryDelimiter : '&'; - - return $uri . http_build_query($params); - } -} diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php deleted file mode 100644 index 3ac98cf..0000000 --- a/src/Grant/AbstractGrant.php +++ /dev/null @@ -1,512 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ -namespace League\OAuth2\Server\Grant; - -use League\Event\EmitterAwareTrait; -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\CryptTrait; -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\AuthCodeEntityInterface; -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; -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\Repositories\UserRepositoryInterface; -use League\OAuth2\Server\RequestEvent; -use League\OAuth2\Server\RequestTypes\AuthorizationRequest; -use Psr\Http\Message\ServerRequestInterface; - -/** - * Abstract grant class. - */ -abstract class AbstractGrant implements GrantTypeInterface -{ - use EmitterAwareTrait, CryptTrait; - - const SCOPE_DELIMITER_STRING = ' '; - - const MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS = 10; - - /** - * @var ClientRepositoryInterface - */ - protected $clientRepository; - - /** - * @var AccessTokenRepositoryInterface - */ - protected $accessTokenRepository; - - /** - * @var ScopeRepositoryInterface - */ - protected $scopeRepository; - - /** - * @var AuthCodeRepositoryInterface - */ - protected $authCodeRepository; - - /** - * @var RefreshTokenRepositoryInterface - */ - protected $refreshTokenRepository; - - /** - * @var UserRepositoryInterface - */ - protected $userRepository; - - /** - * @var \DateInterval - */ - protected $refreshTokenTTL; - - /** - * @var \League\OAuth2\Server\CryptKey - */ - protected $privateKey; - - /** - * @param ClientRepositoryInterface $clientRepository - */ - public function setClientRepository(ClientRepositoryInterface $clientRepository) - { - $this->clientRepository = $clientRepository; - } - - /** - * @param AccessTokenRepositoryInterface $accessTokenRepository - */ - public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository) - { - $this->accessTokenRepository = $accessTokenRepository; - } - - /** - * @param ScopeRepositoryInterface $scopeRepository - */ - public function setScopeRepository(ScopeRepositoryInterface $scopeRepository) - { - $this->scopeRepository = $scopeRepository; - } - - /** - * @param RefreshTokenRepositoryInterface $refreshTokenRepository - */ - public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository) - { - $this->refreshTokenRepository = $refreshTokenRepository; - } - - /** - * @param AuthCodeRepositoryInterface $authCodeRepository - */ - public function setAuthCodeRepository(AuthCodeRepositoryInterface $authCodeRepository) - { - $this->authCodeRepository = $authCodeRepository; - } - - /** - * @param UserRepositoryInterface $userRepository - */ - public function setUserRepository(UserRepositoryInterface $userRepository) - { - $this->userRepository = $userRepository; - } - - /** - * {@inheritdoc} - */ - public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL) - { - $this->refreshTokenTTL = $refreshTokenTTL; - } - - /** - * Set the private key - * - * @param \League\OAuth2\Server\CryptKey $key - */ - public function setPrivateKey(CryptKey $key) - { - $this->privateKey = $key; - } - - /** - * Validate the client. - * - * @param ServerRequestInterface $request - * - * @throws OAuthServerException - * - * @return ClientEntityInterface - */ - protected function validateClient(ServerRequestInterface $request) - { - list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request); - - $clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser); - if (is_null($clientId)) { - throw OAuthServerException::invalidRequest('client_id'); - } - - // If the client is confidential require the client secret - $clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword); - - $client = $this->clientRepository->getClientEntity( - $clientId, - $this->getIdentifier(), - $clientSecret, - true - ); - - if ($client instanceof ClientEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - - // If a redirect URI is provided ensure it matches what is pre-registered - $redirectUri = $this->getRequestParameter('redirect_uri', $request, null); - if ($redirectUri !== null) { - if ( - is_string($client->getRedirectUri()) - && (strcmp($client->getRedirectUri(), $redirectUri) !== 0) - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } elseif ( - is_array($client->getRedirectUri()) - && in_array($redirectUri, $client->getRedirectUri()) === false - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - } - - return $client; - } - - /** - * Validate scopes in the request. - * - * @param string $scopes - * @param string $redirectUri - * - * @throws OAuthServerException - * - * @return ScopeEntityInterface[] - */ - public function validateScopes( - $scopes, - $redirectUri = null - ) { - $scopesList = array_filter( - explode(self::SCOPE_DELIMITER_STRING, trim($scopes)), - function ($scope) { - return !empty($scope); - } - ); - - $scopes = []; - foreach ($scopesList as $scopeItem) { - $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem); - - if ($scope instanceof ScopeEntityInterface === false) { - throw OAuthServerException::invalidScope($scopeItem, $redirectUri); - } - - $scopes[] = $scope; - } - - return $scopes; - } - - /** - * Retrieve request parameter. - * - * @param string $parameter - * @param ServerRequestInterface $request - * @param mixed $default - * - * @return null|string - */ - protected function getRequestParameter($parameter, ServerRequestInterface $request, $default = null) - { - $requestParameters = (array) $request->getParsedBody(); - - return isset($requestParameters[$parameter]) ? $requestParameters[$parameter] : $default; - } - - /** - * Retrieve HTTP Basic Auth credentials with the Authorization header - * of a request. First index of the returned array is the username, - * second is the password (so list() will work). If the header does - * not exist, or is otherwise an invalid HTTP Basic header, return - * [null, null]. - * - * @param ServerRequestInterface $request - * - * @return string[]|null[] - */ - protected function getBasicAuthCredentials(ServerRequestInterface $request) - { - if (!$request->hasHeader('Authorization')) { - return [null, null]; - } - - $header = $request->getHeader('Authorization')[0]; - if (strpos($header, 'Basic ') !== 0) { - return [null, null]; - } - - if (!($decoded = base64_decode(substr($header, 6)))) { - return [null, null]; - } - - if (strpos($decoded, ':') === false) { - return [null, null]; // HTTP Basic header without colon isn't valid - } - - return explode(':', $decoded, 2); - } - - /** - * Retrieve query string parameter. - * - * @param string $parameter - * @param ServerRequestInterface $request - * @param mixed $default - * - * @return null|string - */ - protected function getQueryStringParameter($parameter, ServerRequestInterface $request, $default = null) - { - return isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : $default; - } - - /** - * Retrieve cookie parameter. - * - * @param string $parameter - * @param ServerRequestInterface $request - * @param mixed $default - * - * @return null|string - */ - protected function getCookieParameter($parameter, ServerRequestInterface $request, $default = null) - { - return isset($request->getCookieParams()[$parameter]) ? $request->getCookieParams()[$parameter] : $default; - } - - /** - * Retrieve server parameter. - * - * @param string $parameter - * @param ServerRequestInterface $request - * @param mixed $default - * - * @return null|string - */ - protected function getServerParameter($parameter, ServerRequestInterface $request, $default = null) - { - return isset($request->getServerParams()[$parameter]) ? $request->getServerParams()[$parameter] : $default; - } - - /** - * Issue an access token. - * - * @param \DateInterval $accessTokenTTL - * @param ClientEntityInterface $client - * @param string $userIdentifier - * @param ScopeEntityInterface[] $scopes - * - * @throws OAuthServerException - * @throws UniqueTokenIdentifierConstraintViolationException - * - * @return AccessTokenEntityInterface - */ - protected function issueAccessToken( - \DateInterval $accessTokenTTL, - ClientEntityInterface $client, - $userIdentifier, - array $scopes = [] - ) { - $maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS; - - $accessToken = $this->accessTokenRepository->getNewToken($client, $scopes, $userIdentifier); - $accessToken->setClient($client); - $accessToken->setUserIdentifier($userIdentifier); - $accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL)); - - foreach ($scopes as $scope) { - $accessToken->addScope($scope); - } - - while ($maxGenerationAttempts-- > 0) { - $accessToken->setIdentifier($this->generateUniqueIdentifier()); - try { - $this->accessTokenRepository->persistNewAccessToken($accessToken); - - return $accessToken; - } catch (UniqueTokenIdentifierConstraintViolationException $e) { - if ($maxGenerationAttempts === 0) { - throw $e; - } - } - } - } - - /** - * Issue an auth code. - * - * @param \DateInterval $authCodeTTL - * @param ClientEntityInterface $client - * @param string $userIdentifier - * @param string $redirectUri - * @param ScopeEntityInterface[] $scopes - * - * @throws OAuthServerException - * @throws UniqueTokenIdentifierConstraintViolationException - * - * @return AuthCodeEntityInterface - */ - protected function issueAuthCode( - \DateInterval $authCodeTTL, - ClientEntityInterface $client, - $userIdentifier, - $redirectUri, - array $scopes = [] - ) { - $maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS; - - $authCode = $this->authCodeRepository->getNewAuthCode(); - $authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL)); - $authCode->setClient($client); - $authCode->setUserIdentifier($userIdentifier); - $authCode->setRedirectUri($redirectUri); - - foreach ($scopes as $scope) { - $authCode->addScope($scope); - } - - while ($maxGenerationAttempts-- > 0) { - $authCode->setIdentifier($this->generateUniqueIdentifier()); - try { - $this->authCodeRepository->persistNewAuthCode($authCode); - - return $authCode; - } catch (UniqueTokenIdentifierConstraintViolationException $e) { - if ($maxGenerationAttempts === 0) { - throw $e; - } - } - } - } - - /** - * @param AccessTokenEntityInterface $accessToken - * - * @throws OAuthServerException - * @throws UniqueTokenIdentifierConstraintViolationException - * - * @return RefreshTokenEntityInterface - */ - protected function issueRefreshToken(AccessTokenEntityInterface $accessToken) - { - $maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS; - - $refreshToken = $this->refreshTokenRepository->getNewRefreshToken(); - $refreshToken->setExpiryDateTime((new \DateTime())->add($this->refreshTokenTTL)); - $refreshToken->setAccessToken($accessToken); - - while ($maxGenerationAttempts-- > 0) { - $refreshToken->setIdentifier($this->generateUniqueIdentifier()); - try { - $this->refreshTokenRepository->persistNewRefreshToken($refreshToken); - - return $refreshToken; - } catch (UniqueTokenIdentifierConstraintViolationException $e) { - if ($maxGenerationAttempts === 0) { - throw $e; - } - } - } - } - - /** - * Generate a new unique identifier. - * - * @param int $length - * - * @throws OAuthServerException - * - * @return string - */ - protected function generateUniqueIdentifier($length = 40) - { - try { - return bin2hex(random_bytes($length)); - // @codeCoverageIgnoreStart - } catch (\TypeError $e) { - throw OAuthServerException::serverError('An unexpected error has occurred'); - } catch (\Error $e) { - throw OAuthServerException::serverError('An unexpected error has occurred'); - } catch (\Exception $e) { - // If you get this message, the CSPRNG failed hard. - throw OAuthServerException::serverError('Could not generate a random string'); - } - // @codeCoverageIgnoreEnd - } - - /** - * {@inheritdoc} - */ - public function canRespondToAccessTokenRequest(ServerRequestInterface $request) - { - $requestParameters = (array) $request->getParsedBody(); - - return ( - array_key_exists('grant_type', $requestParameters) - && $requestParameters['grant_type'] === $this->getIdentifier() - ); - } - - /** - * {@inheritdoc} - */ - public function canRespondToAuthorizationRequest(ServerRequestInterface $request) - { - return false; - } - - /** - * {@inheritdoc} - */ - public function validateAuthorizationRequest(ServerRequestInterface $request) - { - throw new \LogicException('This grant cannot validate an authorization request'); - } - - /** - * {@inheritdoc} - */ - public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest) - { - throw new \LogicException('This grant cannot complete an authorization request'); - } -} diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php deleted file mode 100644 index a138366..0000000 --- a/src/Grant/AuthCodeGrant.php +++ /dev/null @@ -1,354 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; -use League\OAuth2\Server\Entities\UserEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface; -use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; -use League\OAuth2\Server\RequestEvent; -use League\OAuth2\Server\RequestTypes\AuthorizationRequest; -use League\OAuth2\Server\ResponseTypes\RedirectResponse; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -class AuthCodeGrant extends AbstractAuthorizeGrant -{ - /** - * @var \DateInterval - */ - private $authCodeTTL; - - /** - * @var bool - */ - private $enableCodeExchangeProof = false; - - /** - * @param AuthCodeRepositoryInterface $authCodeRepository - * @param RefreshTokenRepositoryInterface $refreshTokenRepository - * @param \DateInterval $authCodeTTL - */ - public function __construct( - AuthCodeRepositoryInterface $authCodeRepository, - RefreshTokenRepositoryInterface $refreshTokenRepository, - \DateInterval $authCodeTTL - ) { - $this->setAuthCodeRepository($authCodeRepository); - $this->setRefreshTokenRepository($refreshTokenRepository); - $this->authCodeTTL = $authCodeTTL; - $this->refreshTokenTTL = new \DateInterval('P1M'); - } - - public function enableCodeExchangeProof() - { - $this->enableCodeExchangeProof = true; - } - - /** - * Respond to an access token request. - * - * @param ServerRequestInterface $request - * @param ResponseTypeInterface $responseType - * @param \DateInterval $accessTokenTTL - * - * @throws OAuthServerException - * - * @return ResponseTypeInterface - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ) { - // Validate request - $client = $this->validateClient($request); - $encryptedAuthCode = $this->getRequestParameter('code', $request, null); - - if ($encryptedAuthCode === null) { - throw OAuthServerException::invalidRequest('code'); - } - - // Validate the authorization code - try { - $authCodePayload = json_decode($this->decrypt($encryptedAuthCode)); - if (time() > $authCodePayload->expire_time) { - throw OAuthServerException::invalidRequest('code', 'Authorization code has expired'); - } - - if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) { - throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked'); - } - - if ($authCodePayload->client_id !== $client->getIdentifier()) { - throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client'); - } - - // The redirect URI is required in this request - $redirectUri = $this->getRequestParameter('redirect_uri', $request, null); - if (empty($authCodePayload->redirect_uri) === false && $redirectUri === null) { - throw OAuthServerException::invalidRequest('redirect_uri'); - } - - if ($authCodePayload->redirect_uri !== $redirectUri) { - throw OAuthServerException::invalidRequest('redirect_uri', 'Invalid redirect URI'); - } - - $scopes = []; - foreach ($authCodePayload->scopes as $scopeId) { - $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId); - - if ($scope instanceof ScopeEntityInterface === false) { - // @codeCoverageIgnoreStart - throw OAuthServerException::invalidScope($scopeId); - // @codeCoverageIgnoreEnd - } - - $scopes[] = $scope; - } - - // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes( - $scopes, - $this->getIdentifier(), - $client, - $authCodePayload->user_id - ); - } catch (\LogicException $e) { - throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code'); - } - - // Validate code challenge - if ($this->enableCodeExchangeProof === true) { - $codeVerifier = $this->getRequestParameter('code_verifier', $request, null); - if ($codeVerifier === null) { - throw OAuthServerException::invalidRequest('code_verifier'); - } - - switch ($authCodePayload->code_challenge_method) { - case 'plain': - if (hash_equals($codeVerifier, $authCodePayload->code_challenge) === false) { - throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.'); - } - - break; - case 'S256': - if ( - hash_equals( - urlencode(base64_encode(hash('sha256', $codeVerifier))), - $authCodePayload->code_challenge - ) === false - ) { - throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.'); - } - // @codeCoverageIgnoreStart - break; - default: - throw OAuthServerException::serverError( - sprintf( - 'Unsupported code challenge method `%s`', - $authCodePayload->code_challenge_method - ) - ); - // @codeCoverageIgnoreEnd - } - } - - // Issue and persist access + refresh tokens - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes); - $refreshToken = $this->issueRefreshToken($accessToken); - - // Inject tokens into response type - $responseType->setAccessToken($accessToken); - $responseType->setRefreshToken($refreshToken); - - // Revoke used auth code - $this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id); - - return $responseType; - } - - /** - * Return the grant identifier that can be used in matching up requests. - * - * @return string - */ - public function getIdentifier() - { - return 'authorization_code'; - } - - /** - * {@inheritdoc} - */ - public function canRespondToAuthorizationRequest(ServerRequestInterface $request) - { - return ( - array_key_exists('response_type', $request->getQueryParams()) - && $request->getQueryParams()['response_type'] === 'code' - && isset($request->getQueryParams()['client_id']) - ); - } - - /** - * {@inheritdoc} - */ - public function validateAuthorizationRequest(ServerRequestInterface $request) - { - $clientId = $this->getQueryStringParameter( - 'client_id', - $request, - $this->getServerParameter('PHP_AUTH_USER', $request) - ); - if (is_null($clientId)) { - throw OAuthServerException::invalidRequest('client_id'); - } - - $client = $this->clientRepository->getClientEntity( - $clientId, - $this->getIdentifier(), - null, - false - ); - - if ($client instanceof ClientEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - - $redirectUri = $this->getQueryStringParameter('redirect_uri', $request); - if ($redirectUri !== null) { - if ( - is_string($client->getRedirectUri()) - && (strcmp($client->getRedirectUri(), $redirectUri) !== 0) - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } elseif ( - is_array($client->getRedirectUri()) - && in_array($redirectUri, $client->getRedirectUri()) === false - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - } - - $scopes = $this->validateScopes( - $this->getQueryStringParameter('scope', $request), - is_array($client->getRedirectUri()) - ? $client->getRedirectUri()[0] - : $client->getRedirectUri() - ); - - $stateParameter = $this->getQueryStringParameter('state', $request); - - $authorizationRequest = new AuthorizationRequest(); - $authorizationRequest->setGrantTypeId($this->getIdentifier()); - $authorizationRequest->setClient($client); - $authorizationRequest->setRedirectUri($redirectUri); - $authorizationRequest->setState($stateParameter); - $authorizationRequest->setScopes($scopes); - - if ($this->enableCodeExchangeProof === true) { - $codeChallenge = $this->getQueryStringParameter('code_challenge', $request); - if ($codeChallenge === null) { - throw OAuthServerException::invalidRequest('code_challenge'); - } - - if (preg_match('/^[A-Za-z0-9-._~]{43,128}$/', $codeChallenge) !== 1) { - throw OAuthServerException::invalidRequest( - 'code_challenge', - 'The code_challenge must be between 43 and 128 characters' - ); - } - - $codeChallengeMethod = $this->getQueryStringParameter('code_challenge_method', $request, 'plain'); - if (in_array($codeChallengeMethod, ['plain', 'S256']) === false) { - throw OAuthServerException::invalidRequest( - 'code_challenge_method', - 'Code challenge method must be `plain` or `S256`' - ); - } - - $authorizationRequest->setCodeChallenge($codeChallenge); - $authorizationRequest->setCodeChallengeMethod($codeChallengeMethod); - } - - return $authorizationRequest; - } - - /** - * {@inheritdoc} - */ - public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest) - { - if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) { - throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest'); - } - - $finalRedirectUri = ($authorizationRequest->getRedirectUri() === null) - ? is_array($authorizationRequest->getClient()->getRedirectUri()) - ? $authorizationRequest->getClient()->getRedirectUri()[0] - : $authorizationRequest->getClient()->getRedirectUri() - : $authorizationRequest->getRedirectUri(); - - // The user approved the client, redirect them back with an auth code - if ($authorizationRequest->isAuthorizationApproved() === true) { - $authCode = $this->issueAuthCode( - $this->authCodeTTL, - $authorizationRequest->getClient(), - $authorizationRequest->getUser()->getIdentifier(), - $authorizationRequest->getRedirectUri(), - $authorizationRequest->getScopes() - ); - - $payload = [ - 'client_id' => $authCode->getClient()->getIdentifier(), - 'redirect_uri' => $authCode->getRedirectUri(), - 'auth_code_id' => $authCode->getIdentifier(), - 'scopes' => $authCode->getScopes(), - 'user_id' => $authCode->getUserIdentifier(), - 'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'), - 'code_challenge' => $authorizationRequest->getCodeChallenge(), - 'code_challenge_method' => $authorizationRequest->getCodeChallengeMethod(), - ]; - - $response = new RedirectResponse(); - $response->setRedirectUri( - $this->makeRedirectUri( - $finalRedirectUri, - [ - 'code' => $this->encrypt( - json_encode( - $payload - ) - ), - 'state' => $authorizationRequest->getState(), - ] - ) - ); - - return $response; - } - - // The user denied the client, redirect them back with an error - throw OAuthServerException::accessDenied( - 'The user denied the request', - $this->makeRedirectUri( - $finalRedirectUri, - [ - 'state' => $authorizationRequest->getState(), - ] - ) - ); - } -} diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php deleted file mode 100644 index b5b968d..0000000 --- a/src/Grant/ClientCredentialsGrant.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -/** - * Client credentials grant class. - */ -class ClientCredentialsGrant extends AbstractGrant -{ - /** - * {@inheritdoc} - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ) { - // Validate request - $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); - - // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); - - // Issue and persist access token - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes); - - // Inject access token into response type - $responseType->setAccessToken($accessToken); - - return $responseType; - } - - /** - * {@inheritdoc} - */ - public function getIdentifier() - { - return 'client_credentials'; - } -} diff --git a/src/Grant/GrantTypeInterface.php b/src/Grant/GrantTypeInterface.php deleted file mode 100644 index 7aa9824..0000000 --- a/src/Grant/GrantTypeInterface.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\Event\EmitterAwareInterface; -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; -use League\OAuth2\Server\Repositories\ClientRepositoryInterface; -use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; -use League\OAuth2\Server\RequestTypes\AuthorizationRequest; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -/** - * Grant type interface. - */ -interface GrantTypeInterface extends EmitterAwareInterface -{ - /** - * Set refresh token TTL. - * - * @param \DateInterval $refreshTokenTTL - */ - public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL); - - /** - * Return the grant identifier that can be used in matching up requests. - * - * @return string - */ - public function getIdentifier(); - - /** - * Respond to an incoming request. - * - * @param ServerRequestInterface $request - * @param ResponseTypeInterface $responseType - * @param \DateInterval $accessTokenTTL - * - * @return ResponseTypeInterface - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ); - - /** - * The grant type should return true if it is able to response to an authorization request - * - * @param ServerRequestInterface $request - * - * @return bool - */ - public function canRespondToAuthorizationRequest(ServerRequestInterface $request); - - /** - * If the grant can respond to an authorization request this method should be called to validate the parameters of - * the request. - * - * If the validation is successful an AuthorizationRequest object will be returned. This object can be safely - * serialized in a user's session, and can be used during user authentication and authorization. - * - * @param ServerRequestInterface $request - * - * @return AuthorizationRequest - */ - public function validateAuthorizationRequest(ServerRequestInterface $request); - - /** - * Once a user has authenticated and authorized the client the grant can complete the authorization request. - * The AuthorizationRequest object's $userId property must be set to the authenticated user and the - * $authorizationApproved property must reflect their desire to authorize or deny the client. - * - * @param AuthorizationRequest $authorizationRequest - * - * @return ResponseTypeInterface - */ - public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest); - - /** - * The grant type should return true if it is able to respond to this request. - * - * For example most grant types will check that the $_POST['grant_type'] property matches it's identifier property. - * - * @param ServerRequestInterface $request - * - * @return bool - */ - public function canRespondToAccessTokenRequest(ServerRequestInterface $request); - - /** - * Set the client repository. - * - * @param ClientRepositoryInterface $clientRepository - */ - public function setClientRepository(ClientRepositoryInterface $clientRepository); - - /** - * Set the access token repository. - * - * @param AccessTokenRepositoryInterface $accessTokenRepository - */ - public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository); - - /** - * Set the scope repository. - * - * @param ScopeRepositoryInterface $scopeRepository - */ - public function setScopeRepository(ScopeRepositoryInterface $scopeRepository); - - /** - * Set the path to the private key. - * - * @param CryptKey $privateKey - */ - public function setPrivateKey(CryptKey $privateKey); - - /** - * Set the encryption key - * - * @param string|null $key - */ - public function setEncryptionKey($key = null); -} diff --git a/src/Grant/ImplicitGrant.php b/src/Grant/ImplicitGrant.php deleted file mode 100644 index 2f7ea51..0000000 --- a/src/Grant/ImplicitGrant.php +++ /dev/null @@ -1,225 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\UserEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; -use League\OAuth2\Server\RequestEvent; -use League\OAuth2\Server\RequestTypes\AuthorizationRequest; -use League\OAuth2\Server\ResponseTypes\RedirectResponse; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -class ImplicitGrant extends AbstractAuthorizeGrant -{ - /** - * @var \DateInterval - */ - private $accessTokenTTL; - - /** - * @param \DateInterval $accessTokenTTL - */ - public function __construct(\DateInterval $accessTokenTTL) - { - $this->accessTokenTTL = $accessTokenTTL; - } - - /** - * @param \DateInterval $refreshTokenTTL - * - * @throw \LogicException - */ - public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL) - { - throw new \LogicException('The Implicit Grant does not return refresh tokens'); - } - - /** - * @param RefreshTokenRepositoryInterface $refreshTokenRepository - * - * @throw \LogicException - */ - public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository) - { - throw new \LogicException('The Implicit Grant does not return refresh tokens'); - } - - /** - * {@inheritdoc} - */ - public function canRespondToAccessTokenRequest(ServerRequestInterface $request) - { - return false; - } - - /** - * Return the grant identifier that can be used in matching up requests. - * - * @return string - */ - public function getIdentifier() - { - return 'implicit'; - } - - /** - * Respond to an incoming request. - * - * @param ServerRequestInterface $request - * @param ResponseTypeInterface $responseType - * @param \DateInterval $accessTokenTTL - * - * @return ResponseTypeInterface - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ) { - throw new \LogicException('This grant does not used this method'); - } - - /** - * {@inheritdoc} - */ - public function canRespondToAuthorizationRequest(ServerRequestInterface $request) - { - return ( - isset($request->getQueryParams()['response_type']) - && $request->getQueryParams()['response_type'] === 'token' - && isset($request->getQueryParams()['client_id']) - ); - } - - /** - * {@inheritdoc} - */ - public function validateAuthorizationRequest(ServerRequestInterface $request) - { - $clientId = $this->getQueryStringParameter( - 'client_id', - $request, - $this->getServerParameter('PHP_AUTH_USER', $request) - ); - if (is_null($clientId)) { - throw OAuthServerException::invalidRequest('client_id'); - } - - $client = $this->clientRepository->getClientEntity( - $clientId, - $this->getIdentifier(), - null, - false - ); - - if ($client instanceof ClientEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - - $redirectUri = $this->getQueryStringParameter('redirect_uri', $request); - if ($redirectUri !== null) { - if ( - is_string($client->getRedirectUri()) - && (strcmp($client->getRedirectUri(), $redirectUri) !== 0) - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } elseif ( - is_array($client->getRedirectUri()) - && in_array($redirectUri, $client->getRedirectUri()) === false - ) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); - throw OAuthServerException::invalidClient(); - } - } - - $scopes = $this->validateScopes( - $this->getQueryStringParameter('scope', $request), - is_array($client->getRedirectUri()) - ? $client->getRedirectUri()[0] - : $client->getRedirectUri() - ); - - // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes( - $scopes, - $this->getIdentifier(), - $client - ); - - $stateParameter = $this->getQueryStringParameter('state', $request); - - $authorizationRequest = new AuthorizationRequest(); - $authorizationRequest->setGrantTypeId($this->getIdentifier()); - $authorizationRequest->setClient($client); - $authorizationRequest->setRedirectUri($redirectUri); - $authorizationRequest->setState($stateParameter); - $authorizationRequest->setScopes($scopes); - - return $authorizationRequest; - } - - /** - * {@inheritdoc} - */ - public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest) - { - if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) { - throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest'); - } - - $finalRedirectUri = ($authorizationRequest->getRedirectUri() === null) - ? is_array($authorizationRequest->getClient()->getRedirectUri()) - ? $authorizationRequest->getClient()->getRedirectUri()[0] - : $authorizationRequest->getClient()->getRedirectUri() - : $authorizationRequest->getRedirectUri(); - - // The user approved the client, redirect them back with an access token - if ($authorizationRequest->isAuthorizationApproved() === true) { - $accessToken = $this->issueAccessToken( - $this->accessTokenTTL, - $authorizationRequest->getClient(), - $authorizationRequest->getUser()->getIdentifier(), - $authorizationRequest->getScopes() - ); - - $response = new RedirectResponse(); - $response->setRedirectUri( - $this->makeRedirectUri( - $finalRedirectUri, - [ - 'access_token' => (string) $accessToken->convertToJWT($this->privateKey), - 'token_type' => 'Bearer', - 'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(), - 'state' => $authorizationRequest->getState(), - ], - '#' - ) - ); - - return $response; - } - - // The user denied the client, redirect them back with an error - throw OAuthServerException::accessDenied( - 'The user denied the request', - $this->makeRedirectUri( - $finalRedirectUri, - [ - 'state' => $authorizationRequest->getState(), - ] - ) - ); - } -} diff --git a/src/Grant/PasswordGrant.php b/src/Grant/PasswordGrant.php deleted file mode 100644 index 3175561..0000000 --- a/src/Grant/PasswordGrant.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\UserEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; -use League\OAuth2\Server\Repositories\UserRepositoryInterface; -use League\OAuth2\Server\RequestEvent; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -/** - * Password grant class. - */ -class PasswordGrant extends AbstractGrant -{ - /** - * @param UserRepositoryInterface $userRepository - * @param RefreshTokenRepositoryInterface $refreshTokenRepository - */ - public function __construct( - UserRepositoryInterface $userRepository, - RefreshTokenRepositoryInterface $refreshTokenRepository - ) { - $this->setUserRepository($userRepository); - $this->setRefreshTokenRepository($refreshTokenRepository); - - $this->refreshTokenTTL = new \DateInterval('P1M'); - } - - /** - * {@inheritdoc} - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ) { - // Validate request - $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); - $user = $this->validateUser($request, $client); - - // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier()); - - // Issue and persist new tokens - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes); - $refreshToken = $this->issueRefreshToken($accessToken); - - // Inject tokens into response - $responseType->setAccessToken($accessToken); - $responseType->setRefreshToken($refreshToken); - - return $responseType; - } - - /** - * @param ServerRequestInterface $request - * @param ClientEntityInterface $client - * - * @throws OAuthServerException - * - * @return UserEntityInterface - */ - protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client) - { - $username = $this->getRequestParameter('username', $request); - if (is_null($username)) { - throw OAuthServerException::invalidRequest('username'); - } - - $password = $this->getRequestParameter('password', $request); - if (is_null($password)) { - throw OAuthServerException::invalidRequest('password'); - } - - $user = $this->userRepository->getUserEntityByUserCredentials( - $username, - $password, - $this->getIdentifier(), - $client - ); - if ($user instanceof UserEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request)); - - throw OAuthServerException::invalidCredentials(); - } - - return $user; - } - - /** - * {@inheritdoc} - */ - public function getIdentifier() - { - return 'password'; - } -} diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php deleted file mode 100644 index 53dfdf7..0000000 --- a/src/Grant/RefreshTokenGrant.php +++ /dev/null @@ -1,133 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Grant; - -use League\OAuth2\Server\Entities\ScopeEntityInterface; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; -use League\OAuth2\Server\RequestEvent; -use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; -use Psr\Http\Message\ServerRequestInterface; - -/** - * Refresh token grant. - */ -class RefreshTokenGrant extends AbstractGrant -{ - /** - * @param RefreshTokenRepositoryInterface $refreshTokenRepository - */ - public function __construct(RefreshTokenRepositoryInterface $refreshTokenRepository) - { - $this->setRefreshTokenRepository($refreshTokenRepository); - - $this->refreshTokenTTL = new \DateInterval('P1M'); - } - - /** - * {@inheritdoc} - */ - public function respondToAccessTokenRequest( - ServerRequestInterface $request, - ResponseTypeInterface $responseType, - \DateInterval $accessTokenTTL - ) { - // Validate request - $client = $this->validateClient($request); - $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); - - // If no new scopes are requested then give the access token the original session scopes - if (count($scopes) === 0) { - $scopes = array_map(function ($scopeId) use ($client) { - $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId); - - if ($scope instanceof ScopeEntityInterface === false) { - // @codeCoverageIgnoreStart - throw OAuthServerException::invalidScope($scopeId); - // @codeCoverageIgnoreEnd - } - - return $scope; - }, $oldRefreshToken['scopes']); - } else { - // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure - // the request doesn't include any new scopes - foreach ($scopes as $scope) { - if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) { - throw OAuthServerException::invalidScope($scope->getIdentifier()); - } - } - } - - // Expire old tokens - $this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']); - $this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']); - - // Issue and persist new tokens - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes); - $refreshToken = $this->issueRefreshToken($accessToken); - - // Inject tokens into response - $responseType->setAccessToken($accessToken); - $responseType->setRefreshToken($refreshToken); - - return $responseType; - } - - /** - * @param ServerRequestInterface $request - * @param string $clientId - * - * @throws OAuthServerException - * - * @return array - */ - protected function validateOldRefreshToken(ServerRequestInterface $request, $clientId) - { - $encryptedRefreshToken = $this->getRequestParameter('refresh_token', $request); - if (is_null($encryptedRefreshToken)) { - throw OAuthServerException::invalidRequest('refresh_token'); - } - - // Validate refresh token - try { - $refreshToken = $this->decrypt($encryptedRefreshToken); - } catch (\Exception $e) { - throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token'); - } - - $refreshTokenData = json_decode($refreshToken, true); - if ($refreshTokenData['client_id'] !== $clientId) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request)); - throw OAuthServerException::invalidRefreshToken('Token is not linked to client'); - } - - if ($refreshTokenData['expire_time'] < time()) { - throw OAuthServerException::invalidRefreshToken('Token has expired'); - } - - if ($this->refreshTokenRepository->isRefreshTokenRevoked($refreshTokenData['refresh_token_id']) === true) { - throw OAuthServerException::invalidRefreshToken('Token has been revoked'); - } - - return $refreshTokenData; - } - - /** - * {@inheritdoc} - */ - public function getIdentifier() - { - return 'refresh_token'; - } -} diff --git a/src/Middleware/AuthorizationServerMiddleware.php b/src/Middleware/AuthorizationServerMiddleware.php deleted file mode 100644 index a5f102f..0000000 --- a/src/Middleware/AuthorizationServerMiddleware.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Middleware; - -use League\OAuth2\Server\AuthorizationServer; -use League\OAuth2\Server\Exception\OAuthServerException; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; - -class AuthorizationServerMiddleware -{ - /** - * @var AuthorizationServer - */ - private $server; - - /** - * @param AuthorizationServer $server - */ - public function __construct(AuthorizationServer $server) - { - $this->server = $server; - } - - /** - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @param callable $next - * - * @return ResponseInterface - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next) - { - try { - $response = $this->server->respondToAccessTokenRequest($request, $response); - } catch (OAuthServerException $exception) { - return $exception->generateHttpResponse($response); - // @codeCoverageIgnoreStart - } catch (\Exception $exception) { - return (new OAuthServerException($exception->getMessage(), 0, 'unknown_error', 500)) - ->generateHttpResponse($response); - // @codeCoverageIgnoreEnd - } - - // Pass the request and response on to the next responder in the chain - return $next($request, $response); - } -} diff --git a/src/Middleware/ResourceServerMiddleware.php b/src/Middleware/ResourceServerMiddleware.php deleted file mode 100644 index 56d28ae..0000000 --- a/src/Middleware/ResourceServerMiddleware.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Middleware; - -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\ResourceServer; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; - -class ResourceServerMiddleware -{ - /** - * @var ResourceServer - */ - private $server; - - /** - * @param ResourceServer $server - */ - public function __construct(ResourceServer $server) - { - $this->server = $server; - } - - /** - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @param callable $next - * - * @return \Psr\Http\Message\ResponseInterface - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next) - { - try { - $request = $this->server->validateAuthenticatedRequest($request); - } catch (OAuthServerException $exception) { - return $exception->generateHttpResponse($response); - // @codeCoverageIgnoreStart - } catch (\Exception $exception) { - return (new OAuthServerException($exception->getMessage(), 0, 'unknown_error', 500)) - ->generateHttpResponse($response); - // @codeCoverageIgnoreEnd - } - - // Pass the request and response on to the next responder in the chain - return $next($request, $response); - } -} diff --git a/src/Repositories/AccessTokenRepositoryInterface.php b/src/Repositories/AccessTokenRepositoryInterface.php deleted file mode 100644 index 72ddf1f..0000000 --- a/src/Repositories/AccessTokenRepositoryInterface.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; -use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; - -/** - * Access token interface. - */ -interface AccessTokenRepositoryInterface extends RepositoryInterface -{ - /** - * Create a new access token - * - * @param ClientEntityInterface $clientEntity - * @param ScopeEntityInterface[] $scopes - * @param mixed $userIdentifier - * - * @return AccessTokenEntityInterface - */ - public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null); - - /** - * Persists a new access token to permanent storage. - * - * @param AccessTokenEntityInterface $accessTokenEntity - * - * @throws UniqueTokenIdentifierConstraintViolationException - */ - public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity); - - /** - * Revoke an access token. - * - * @param string $tokenId - */ - public function revokeAccessToken($tokenId); - - /** - * Check if the access token has been revoked. - * - * @param string $tokenId - * - * @return bool Return true if this token has been revoked - */ - public function isAccessTokenRevoked($tokenId); -} diff --git a/src/Repositories/AuthCodeRepositoryInterface.php b/src/Repositories/AuthCodeRepositoryInterface.php deleted file mode 100644 index 2dc285b..0000000 --- a/src/Repositories/AuthCodeRepositoryInterface.php +++ /dev/null @@ -1,51 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\AuthCodeEntityInterface; -use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; - -/** - * Auth code storage interface. - */ -interface AuthCodeRepositoryInterface extends RepositoryInterface -{ - /** - * Creates a new AuthCode - * - * @return AuthCodeEntityInterface - */ - public function getNewAuthCode(); - - /** - * Persists a new auth code to permanent storage. - * - * @param AuthCodeEntityInterface $authCodeEntity - * - * @throws UniqueTokenIdentifierConstraintViolationException - */ - public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity); - - /** - * Revoke an auth code. - * - * @param string $codeId - */ - public function revokeAuthCode($codeId); - - /** - * Check if the auth code has been revoked. - * - * @param string $codeId - * - * @return bool Return true if this code has been revoked - */ - public function isAuthCodeRevoked($codeId); -} diff --git a/src/Repositories/ClientRepositoryInterface.php b/src/Repositories/ClientRepositoryInterface.php deleted file mode 100644 index 34adf56..0000000 --- a/src/Repositories/ClientRepositoryInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\ClientEntityInterface; - -/** - * Client storage interface. - */ -interface ClientRepositoryInterface extends RepositoryInterface -{ - /** - * Get a client. - * - * @param string $clientIdentifier The client's identifier - * @param string $grantType The grant type used - * @param null|string $clientSecret The client's secret (if sent) - * @param bool $mustValidateSecret If true the client must attempt to validate the secret if the client - * is confidential - * - * @return ClientEntityInterface - */ - public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true); -} diff --git a/src/Repositories/RefreshTokenRepositoryInterface.php b/src/Repositories/RefreshTokenRepositoryInterface.php deleted file mode 100644 index 0c0697b..0000000 --- a/src/Repositories/RefreshTokenRepositoryInterface.php +++ /dev/null @@ -1,51 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; -use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; - -/** - * Refresh token interface. - */ -interface RefreshTokenRepositoryInterface extends RepositoryInterface -{ - /** - * Creates a new refresh token - * - * @return RefreshTokenEntityInterface - */ - public function getNewRefreshToken(); - - /** - * Create a new refresh token_name. - * - * @param RefreshTokenEntityInterface $refreshTokenEntity - * - * @throws UniqueTokenIdentifierConstraintViolationException - */ - public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity); - - /** - * Revoke the refresh token. - * - * @param string $tokenId - */ - public function revokeRefreshToken($tokenId); - - /** - * Check if the refresh token has been revoked. - * - * @param string $tokenId - * - * @return bool Return true if this token has been revoked - */ - public function isRefreshTokenRevoked($tokenId); -} diff --git a/src/Repositories/RepositoryInterface.php b/src/Repositories/RepositoryInterface.php deleted file mode 100644 index 9c27b4b..0000000 --- a/src/Repositories/RepositoryInterface.php +++ /dev/null @@ -1,17 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -/** - * Repository interface. - */ -interface RepositoryInterface -{ -} diff --git a/src/Repositories/ScopeRepositoryInterface.php b/src/Repositories/ScopeRepositoryInterface.php deleted file mode 100644 index 52db05d..0000000 --- a/src/Repositories/ScopeRepositoryInterface.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; - -/** - * Scope interface. - */ -interface ScopeRepositoryInterface extends RepositoryInterface -{ - /** - * Return information about a scope. - * - * @param string $identifier The scope identifier - * - * @return ScopeEntityInterface - */ - public function getScopeEntityByIdentifier($identifier); - - /** - * Given a client, grant type and optional user identifier validate the set of scopes requested are valid and optionally - * append additional scopes or remove requested scopes. - * - * @param ScopeEntityInterface[] $scopes - * @param string $grantType - * @param ClientEntityInterface $clientEntity - * @param null|string $userIdentifier - * - * @return ScopeEntityInterface[] - */ - public function finalizeScopes( - array $scopes, - $grantType, - ClientEntityInterface $clientEntity, - $userIdentifier = null - ); -} diff --git a/src/Repositories/UserRepositoryInterface.php b/src/Repositories/UserRepositoryInterface.php deleted file mode 100644 index 0a9efef..0000000 --- a/src/Repositories/UserRepositoryInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\Repositories; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\UserEntityInterface; - -interface UserRepositoryInterface extends RepositoryInterface -{ - /** - * Get a user entity. - * - * @param string $username - * @param string $password - * @param string $grantType The grant type used - * @param ClientEntityInterface $clientEntity - * - * @return UserEntityInterface - */ - public function getUserEntityByUserCredentials( - $username, - $password, - $grantType, - ClientEntityInterface $clientEntity - ); -} diff --git a/src/RequestEvent.php b/src/RequestEvent.php deleted file mode 100644 index 1558e11..0000000 --- a/src/RequestEvent.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server; - -use League\Event\Event; -use Psr\Http\Message\ServerRequestInterface; - -class RequestEvent extends Event -{ - const CLIENT_AUTHENTICATION_FAILED = 'client.authentication.failed'; - const USER_AUTHENTICATION_FAILED = 'user.authentication.failed'; - const REFRESH_TOKEN_CLIENT_FAILED = 'refresh_token.client.failed'; - - /** - * @var ServerRequestInterface - */ - private $request; - - /** - * RequestEvent constructor. - * - * @param string $name - * @param ServerRequestInterface $request - */ - public function __construct($name, ServerRequestInterface $request) - { - parent::__construct($name); - $this->request = $request; - } - - /** - * @return ServerRequestInterface - * @codeCoverageIgnore - */ - public function getRequest() - { - return $this->request; - } -} diff --git a/src/RequestTypes/AuthorizationRequest.php b/src/RequestTypes/AuthorizationRequest.php deleted file mode 100644 index 41bfb50..0000000 --- a/src/RequestTypes/AuthorizationRequest.php +++ /dev/null @@ -1,224 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\RequestTypes; - -use League\OAuth2\Server\Entities\ClientEntityInterface; -use League\OAuth2\Server\Entities\ScopeEntityInterface; -use League\OAuth2\Server\Entities\UserEntityInterface; - -class AuthorizationRequest -{ - /** - * The grant type identifier - * - * @var string - */ - protected $grantTypeId; - - /** - * The client identifier - * - * @var ClientEntityInterface - */ - protected $client; - - /** - * The user identifier - * - * @var UserEntityInterface - */ - protected $user; - - /** - * An array of scope identifiers - * - * @var ScopeEntityInterface[] - */ - protected $scopes = []; - - /** - * Has the user authorized the authorization request - * - * @var bool - */ - protected $authorizationApproved = false; - - /** - * The redirect URI used in the request - * - * @var string - */ - protected $redirectUri; - - /** - * The state parameter on the authorization request - * - * @var string - */ - protected $state; - - /** - * The code challenge (if provided) - * - * @var string - */ - protected $codeChallenge; - - /** - * The code challenge method (if provided) - * - * @var string - */ - protected $codeChallengeMethod; - - /** - * @return string - */ - public function getGrantTypeId() - { - return $this->grantTypeId; - } - - /** - * @param string $grantTypeId - */ - public function setGrantTypeId($grantTypeId) - { - $this->grantTypeId = $grantTypeId; - } - - /** - * @return ClientEntityInterface - */ - public function getClient() - { - return $this->client; - } - - /** - * @param ClientEntityInterface $client - */ - public function setClient(ClientEntityInterface $client) - { - $this->client = $client; - } - - /** - * @return UserEntityInterface - */ - public function getUser() - { - return $this->user; - } - - /** - * @param UserEntityInterface $user - */ - public function setUser(UserEntityInterface $user) - { - $this->user = $user; - } - - /** - * @return ScopeEntityInterface[] - */ - public function getScopes() - { - return $this->scopes; - } - - /** - * @param ScopeEntityInterface[] $scopes - */ - public function setScopes(array $scopes) - { - $this->scopes = $scopes; - } - - /** - * @return bool - */ - public function isAuthorizationApproved() - { - return $this->authorizationApproved; - } - - /** - * @param bool $authorizationApproved - */ - public function setAuthorizationApproved($authorizationApproved) - { - $this->authorizationApproved = $authorizationApproved; - } - - /** - * @return string - */ - public function getRedirectUri() - { - return $this->redirectUri; - } - - /** - * @param string $redirectUri - */ - public function setRedirectUri($redirectUri) - { - $this->redirectUri = $redirectUri; - } - - /** - * @return string - */ - public function getState() - { - return $this->state; - } - - /** - * @param string $state - */ - public function setState($state) - { - $this->state = $state; - } - - /** - * @return string - */ - public function getCodeChallenge() - { - return $this->codeChallenge; - } - - /** - * @param string $codeChallenge - */ - public function setCodeChallenge($codeChallenge) - { - $this->codeChallenge = $codeChallenge; - } - - /** - * @return string - */ - public function getCodeChallengeMethod() - { - return $this->codeChallengeMethod; - } - - /** - * @param string $codeChallengeMethod - */ - public function setCodeChallengeMethod($codeChallengeMethod) - { - $this->codeChallengeMethod = $codeChallengeMethod; - } -} diff --git a/src/ResourceServer.php b/src/ResourceServer.php deleted file mode 100644 index 5e9c13f..0000000 --- a/src/ResourceServer.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server; - -use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface; -use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; -use Psr\Http\Message\ServerRequestInterface; - -class ResourceServer -{ - /** - * @var AccessTokenRepositoryInterface - */ - private $accessTokenRepository; - - /** - * @var CryptKey - */ - private $publicKey; - - /** - * @var null|AuthorizationValidatorInterface - */ - private $authorizationValidator; - - /** - * New server instance. - * - * @param AccessTokenRepositoryInterface $accessTokenRepository - * @param CryptKey|string $publicKey - * @param null|AuthorizationValidatorInterface $authorizationValidator - */ - public function __construct( - AccessTokenRepositoryInterface $accessTokenRepository, - $publicKey, - AuthorizationValidatorInterface $authorizationValidator = null - ) { - $this->accessTokenRepository = $accessTokenRepository; - - if ($publicKey instanceof CryptKey === false) { - $publicKey = new CryptKey($publicKey); - } - $this->publicKey = $publicKey; - - $this->authorizationValidator = $authorizationValidator; - } - - /** - * @return AuthorizationValidatorInterface - */ - protected function getAuthorizationValidator() - { - if ($this->authorizationValidator instanceof AuthorizationValidatorInterface === false) { - $this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository); - } - - $this->authorizationValidator->setPublicKey($this->publicKey); - - return $this->authorizationValidator; - } - - /** - * Determine the access token validity. - * - * @param ServerRequestInterface $request - * - * @throws OAuthServerException - * - * @return ServerRequestInterface - */ - public function validateAuthenticatedRequest(ServerRequestInterface $request) - { - return $this->getAuthorizationValidator()->validateAuthorization($request); - } -} diff --git a/src/ResponseTypes/AbstractResponseType.php b/src/ResponseTypes/AbstractResponseType.php deleted file mode 100644 index 0c256f1..0000000 --- a/src/ResponseTypes/AbstractResponseType.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\ResponseTypes; - -use League\OAuth2\Server\CryptKey; -use League\OAuth2\Server\CryptTrait; -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; - -abstract class AbstractResponseType implements ResponseTypeInterface -{ - use CryptTrait; - - /** - * @var AccessTokenEntityInterface - */ - protected $accessToken; - - /** - * @var RefreshTokenEntityInterface - */ - protected $refreshToken; - - /** - * @var CryptKey - */ - protected $privateKey; - - /** - * {@inheritdoc} - */ - public function setAccessToken(AccessTokenEntityInterface $accessToken) - { - $this->accessToken = $accessToken; - } - - /** - * {@inheritdoc} - */ - public function setRefreshToken(RefreshTokenEntityInterface $refreshToken) - { - $this->refreshToken = $refreshToken; - } - - /** - * Set the private key - * - * @param \League\OAuth2\Server\CryptKey $key - */ - public function setPrivateKey(CryptKey $key) - { - $this->privateKey = $key; - } - -} diff --git a/src/ResponseTypes/BearerTokenResponse.php b/src/ResponseTypes/BearerTokenResponse.php deleted file mode 100644 index a57573a..0000000 --- a/src/ResponseTypes/BearerTokenResponse.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\ResponseTypes; - -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; -use Psr\Http\Message\ResponseInterface; - -class BearerTokenResponse extends AbstractResponseType -{ - /** - * {@inheritdoc} - */ - public function generateHttpResponse(ResponseInterface $response) - { - $expireDateTime = $this->accessToken->getExpiryDateTime()->getTimestamp(); - - $jwtAccessToken = $this->accessToken->convertToJWT($this->privateKey); - - $responseParams = [ - 'token_type' => 'Bearer', - 'expires_in' => $expireDateTime - (new \DateTime())->getTimestamp(), - 'access_token' => (string) $jwtAccessToken, - ]; - - if ($this->refreshToken instanceof RefreshTokenEntityInterface) { - $refreshToken = $this->encrypt( - json_encode( - [ - 'client_id' => $this->accessToken->getClient()->getIdentifier(), - 'refresh_token_id' => $this->refreshToken->getIdentifier(), - 'access_token_id' => $this->accessToken->getIdentifier(), - 'scopes' => $this->accessToken->getScopes(), - 'user_id' => $this->accessToken->getUserIdentifier(), - 'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(), - ] - ) - ); - - $responseParams['refresh_token'] = $refreshToken; - } - - $responseParams = array_merge($this->getExtraParams($this->accessToken), $responseParams); - - $response = $response - ->withStatus(200) - ->withHeader('pragma', 'no-cache') - ->withHeader('cache-control', 'no-store') - ->withHeader('content-type', 'application/json; charset=UTF-8'); - - $response->getBody()->write(json_encode($responseParams)); - - return $response; - } - - /** - * Add custom fields to your Bearer Token response here, then override - * AuthorizationServer::getResponseType() to pull in your version of - * this class rather than the default. - * - * @param AccessTokenEntityInterface $accessToken - * - * @return array - */ - protected function getExtraParams(AccessTokenEntityInterface $accessToken) - { - return []; - } -} diff --git a/src/ResponseTypes/RedirectResponse.php b/src/ResponseTypes/RedirectResponse.php deleted file mode 100644 index e463914..0000000 --- a/src/ResponseTypes/RedirectResponse.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\ResponseTypes; - -use Psr\Http\Message\ResponseInterface; - -class RedirectResponse extends AbstractResponseType -{ - /** - * @var string - */ - private $redirectUri; - - /** - * @param string $redirectUri - */ - public function setRedirectUri($redirectUri) - { - $this->redirectUri = $redirectUri; - } - - /** - * @param ResponseInterface $response - * - * @return ResponseInterface - */ - public function generateHttpResponse(ResponseInterface $response) - { - return $response->withStatus(302)->withHeader('Location', $this->redirectUri); - } -} diff --git a/src/ResponseTypes/ResponseTypeInterface.php b/src/ResponseTypes/ResponseTypeInterface.php deleted file mode 100644 index 8ac20b8..0000000 --- a/src/ResponseTypes/ResponseTypeInterface.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright Copyright (c) Alex Bilbie - * @license http://mit-license.org/ - * - * @link https://github.com/thephpleague/oauth2-server - */ - -namespace League\OAuth2\Server\ResponseTypes; - -use League\OAuth2\Server\Entities\AccessTokenEntityInterface; -use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; -use Psr\Http\Message\ResponseInterface; - -interface ResponseTypeInterface -{ - /** - * @param AccessTokenEntityInterface $accessToken - */ - public function setAccessToken(AccessTokenEntityInterface $accessToken); - - /** - * @param RefreshTokenEntityInterface $refreshToken - */ - public function setRefreshToken(RefreshTokenEntityInterface $refreshToken); - - /** - * @param ResponseInterface $response - * - * @return ResponseInterface - */ - public function generateHttpResponse(ResponseInterface $response); - - /** - * Set the encryption key - * - * @param string|null $key - */ - public function setEncryptionKey($key = null); -}