Jwt.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. namespace sizeg\jwt;
  3. use Lcobucci\JWT\Builder;
  4. use Lcobucci\JWT\Claim\Factory as ClaimFactory;
  5. use Lcobucci\JWT\Parser;
  6. use Lcobucci\JWT\Parsing\Decoder;
  7. use Lcobucci\JWT\Parsing\Encoder;
  8. use Lcobucci\JWT\Signer;
  9. use Lcobucci\JWT\Signer\Key;
  10. use Lcobucci\JWT\Token;
  11. use Lcobucci\JWT\ValidationData;
  12. use Yii;
  13. use yii\base\Component;
  14. use yii\base\InvalidArgumentException;
  15. /**
  16. * JSON Web Token implementation, based on this library:
  17. * https://github.com/lcobucci/jwt
  18. *
  19. * @author Dmitriy Demin <sizemail@gmail.com>
  20. * @since 1.0.0-a
  21. */
  22. class Jwt extends Component
  23. {
  24. /**
  25. * @var array Supported algorithms
  26. */
  27. public $supportedAlgs = [
  28. 'HS256' => \Lcobucci\JWT\Signer\Hmac\Sha256::class,
  29. 'HS384' => \Lcobucci\JWT\Signer\Hmac\Sha384::class,
  30. 'HS512' => \Lcobucci\JWT\Signer\Hmac\Sha512::class,
  31. 'ES256' => \Lcobucci\JWT\Signer\Ecdsa\Sha256::class,
  32. 'ES384' => \Lcobucci\JWT\Signer\Ecdsa\Sha384::class,
  33. 'ES512' => \Lcobucci\JWT\Signer\Ecdsa\Sha512::class,
  34. 'RS256' => \Lcobucci\JWT\Signer\Rsa\Sha256::class,
  35. 'RS384' => \Lcobucci\JWT\Signer\Rsa\Sha384::class,
  36. 'RS512' => \Lcobucci\JWT\Signer\Rsa\Sha512::class,
  37. ];
  38. /**
  39. * @var Key|string $key The key
  40. */
  41. public $key;
  42. /**
  43. * @var string|array|callable \sizeg\jwtJwtValidationData
  44. * @see [[Yii::createObject()]]
  45. */
  46. public $jwtValidationData = JwtValidationData::class;
  47. /**
  48. * @see [[Lcobucci\JWT\Builder::__construct()]]
  49. * @param Encoder|null $encoder
  50. * @param ClaimFactory|null $claimFactory
  51. * @return Builder
  52. */
  53. public function getBuilder(Encoder $encoder = null, ClaimFactory $claimFactory = null)
  54. {
  55. return new Builder($encoder, $claimFactory);
  56. }
  57. /**
  58. * @see [[Lcobucci\JWT\Parser::__construct()]]
  59. * @param Decoder|null $decoder
  60. * @param ClaimFactory|null $claimFactory
  61. * @return Parser
  62. */
  63. public function getParser(Decoder $decoder = null, ClaimFactory $claimFactory = null)
  64. {
  65. return new Parser($decoder, $claimFactory);
  66. }
  67. /**
  68. * @see [[Lcobucci\JWT\ValidationData::__construct()]]
  69. * @return ValidationData
  70. */
  71. public function getValidationData()
  72. {
  73. return Yii::createObject($this->jwtValidationData)->getValidationData();
  74. }
  75. /**
  76. * @param string $alg
  77. * @return Signer
  78. */
  79. public function getSigner($alg)
  80. {
  81. $class = $this->supportedAlgs[$alg];
  82. return new $class();
  83. }
  84. /**
  85. * @param strng $content
  86. * @param string|null $passphrase
  87. * @return Key
  88. */
  89. public function getKey($content = null, $passphrase = null)
  90. {
  91. $content = $content ?: $this->key;
  92. if ($content instanceof Key) {
  93. return $content;
  94. }
  95. return new Key($content, $passphrase);
  96. }
  97. /**
  98. * Parses the JWT and returns a token class
  99. * @param string $token JWT
  100. * @param bool $validate
  101. * @param bool $verify
  102. * @return Token|null
  103. * @throws \Throwable
  104. */
  105. public function loadToken($token, $validate = true, $verify = true)
  106. {
  107. try {
  108. $token = $this->getParser()->parse((string) $token);
  109. } catch (\RuntimeException $e) {
  110. Yii::warning('Invalid JWT provided: ' . $e->getMessage(), 'jwt');
  111. return null;
  112. } catch (\InvalidArgumentException $e) {
  113. Yii::warning('Invalid JWT provided: ' . $e->getMessage(), 'jwt');
  114. return null;
  115. }
  116. if ($validate && !$this->validateToken($token)) {
  117. return null;
  118. }
  119. if ($verify && !$this->verifyToken($token)) {
  120. return null;
  121. }
  122. return $token;
  123. }
  124. /**
  125. * Validate token
  126. * @param Token $token token object
  127. * @param int|null $currentTime
  128. * @return bool
  129. */
  130. public function validateToken(Token $token, $currentTime = null)
  131. {
  132. $validationData = $this->getValidationData();
  133. if ($currentTime !== null) {
  134. $validationData->setCurrentTime($currentTime);
  135. }
  136. return $token->validate($validationData);
  137. }
  138. /**
  139. * Validate token
  140. * @param Token $token token object
  141. * @return bool
  142. * @throws \Throwable
  143. */
  144. public function verifyToken(Token $token)
  145. {
  146. $alg = $token->getHeader('alg');
  147. if (empty($this->supportedAlgs[$alg])) {
  148. throw new InvalidArgumentException('Algorithm not supported');
  149. }
  150. /** @var Signer $signer */
  151. $signer = Yii::createObject($this->supportedAlgs[$alg]);
  152. return $token->verify($signer, $this->key);
  153. }
  154. }