vendor/league/oauth2-server/src/AuthorizationValidators/BearerTokenValidator.php line 101

Open in your IDE?
  1. <?php
  2. /**
  3. * @author Alex Bilbie <hello@alexbilbie.com>
  4. * @copyright Copyright (c) Alex Bilbie
  5. * @license http://mit-license.org/
  6. *
  7. * @link https://github.com/thephpleague/oauth2-server
  8. */
  9. namespace League\OAuth2\Server\AuthorizationValidators;
  10. use DateTimeZone;
  11. use Lcobucci\Clock\SystemClock;
  12. use Lcobucci\JWT\Configuration;
  13. use Lcobucci\JWT\Signer\Key\InMemory;
  14. use Lcobucci\JWT\Signer\Rsa\Sha256;
  15. use Lcobucci\JWT\Validation\Constraint\SignedWith;
  16. use Lcobucci\JWT\Validation\Constraint\LooseValidAt;
  17. use Lcobucci\JWT\Validation\Constraint\ValidAt;
  18. use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
  19. use League\OAuth2\Server\CryptKey;
  20. use League\OAuth2\Server\CryptTrait;
  21. use League\OAuth2\Server\Exception\OAuthServerException;
  22. use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
  23. use Psr\Http\Message\ServerRequestInterface;
  24. class BearerTokenValidator implements AuthorizationValidatorInterface
  25. {
  26. use CryptTrait;
  27. /**
  28. * @var AccessTokenRepositoryInterface
  29. */
  30. private $accessTokenRepository;
  31. /**
  32. * @var CryptKey
  33. */
  34. protected $publicKey;
  35. /**
  36. * @var Configuration
  37. */
  38. private $jwtConfiguration;
  39. /**
  40. * @param AccessTokenRepositoryInterface $accessTokenRepository
  41. */
  42. public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
  43. {
  44. $this->accessTokenRepository = $accessTokenRepository;
  45. }
  46. /**
  47. * Set the public key
  48. *
  49. * @param CryptKey $key
  50. */
  51. public function setPublicKey(CryptKey $key)
  52. {
  53. $this->publicKey = $key;
  54. $this->initJwtConfiguration();
  55. }
  56. /**
  57. * Initialise the JWT configuration.
  58. */
  59. private function initJwtConfiguration()
  60. {
  61. $this->jwtConfiguration = Configuration::forSymmetricSigner(
  62. new Sha256(),
  63. InMemory::plainText('empty', 'empty')
  64. );
  65. $this->jwtConfiguration->setValidationConstraints(
  66. \class_exists(LooseValidAt::class)
  67. ? new LooseValidAt(new SystemClock(new DateTimeZone(\date_default_timezone_get())))
  68. : new ValidAt(new SystemClock(new DateTimeZone(\date_default_timezone_get()))),
  69. new SignedWith(
  70. new Sha256(),
  71. InMemory::plainText($this->publicKey->getKeyContents(), $this->publicKey->getPassPhrase() ?? '')
  72. )
  73. );
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. public function validateAuthorization(ServerRequestInterface $request)
  79. {
  80. if ($request->hasHeader('authorization') === false) {
  81. throw OAuthServerException::accessDenied('Missing "Authorization" header');
  82. }
  83. $header = $request->getHeader('authorization');
  84. $jwt = \trim((string) \preg_replace('/^\s*Bearer\s/', '', $header[0]));
  85. try {
  86. // Attempt to parse the JWT
  87. $token = $this->jwtConfiguration->parser()->parse($jwt);
  88. } catch (\Lcobucci\JWT\Exception $exception) {
  89. throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception);
  90. }
  91. try {
  92. // Attempt to validate the JWT
  93. $constraints = $this->jwtConfiguration->validationConstraints();
  94. $this->jwtConfiguration->validator()->assert($token, ...$constraints);
  95. } catch (RequiredConstraintsViolated $exception) {
  96. throw OAuthServerException::accessDenied('Access token could not be verified');
  97. }
  98. $claims = $token->claims();
  99. // Check if token has been revoked
  100. if ($this->accessTokenRepository->isAccessTokenRevoked($claims->get('jti'))) {
  101. throw OAuthServerException::accessDenied('Access token has been revoked');
  102. }
  103. // Return the request with additional attributes
  104. return $request
  105. ->withAttribute('oauth_access_token_id', $claims->get('jti'))
  106. ->withAttribute('oauth_client_id', $this->convertSingleRecordAudToString($claims->get('aud')))
  107. ->withAttribute('oauth_user_id', $claims->get('sub'))
  108. ->withAttribute('oauth_scopes', $claims->get('scopes'));
  109. }
  110. /**
  111. * Convert single record arrays into strings to ensure backwards compatibility between v4 and v3.x of lcobucci/jwt
  112. *
  113. * @param mixed $aud
  114. *
  115. * @return array|string
  116. */
  117. private function convertSingleRecordAudToString($aud)
  118. {
  119. return \is_array($aud) && \count($aud) === 1 ? $aud[0] : $aud;
  120. }
  121. }