* @copyright Copyright (c) Alex Bilbie * @license http://mit-license.org/ * * @link https://github.com/thephpleague/oauth2-server */ namespace League\OAuth2\Server\AuthorizationValidators; use BadMethodCallException; use InvalidArgumentException; 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; use RuntimeException; class BearerTokenValidator implements AuthorizationValidatorInterface { use CryptTrait; /** * @var AccessTokenRepositoryInterface */ private $accessTokenRepository; /** * @var CryptKey */ protected $publicKey; /** * @param AccessTokenRepositoryInterface $accessTokenRepository */ public function __construct(AccessTokenRepositoryInterface $accessTokenRepository) { $this->accessTokenRepository = $accessTokenRepository; } /** * Set the public key * * @param 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); try { if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) { throw OAuthServerException::accessDenied('Access token could not be verified'); } } catch (BadMethodCallException $exception) { throw OAuthServerException::accessDenied('Access token is not signed', null, $exception); } // 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(), null, $exception); } catch (RuntimeException $exception) { //JWR couldn't be parsed so return the request as is throw OAuthServerException::accessDenied('Error while decoding to JSON', null, $exception); } } }