Parser.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. /**
  3. * This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
  4. *
  5. * @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
  6. */
  7. namespace Lcobucci\JWT;
  8. use InvalidArgumentException;
  9. use Lcobucci\JWT\Claim\Factory as ClaimFactory;
  10. use Lcobucci\JWT\Parsing\Decoder;
  11. /**
  12. * This class parses the JWT strings and convert them into tokens
  13. *
  14. * @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
  15. * @since 0.1.0
  16. */
  17. class Parser
  18. {
  19. /**
  20. * The data decoder
  21. *
  22. * @var Decoder
  23. */
  24. private $decoder;
  25. /**
  26. * The claims factory
  27. *
  28. * @var ClaimFactory
  29. */
  30. private $claimFactory;
  31. /**
  32. * Initializes the object
  33. *
  34. * @param Decoder $decoder
  35. * @param ClaimFactory $claimFactory
  36. */
  37. public function __construct(
  38. Decoder $decoder = null,
  39. ClaimFactory $claimFactory = null
  40. ) {
  41. $this->decoder = $decoder ?: new Decoder();
  42. $this->claimFactory = $claimFactory ?: new ClaimFactory();
  43. }
  44. /**
  45. * Parses the JWT and returns a token
  46. *
  47. * @param string $jwt
  48. *
  49. * @return Token
  50. */
  51. public function parse($jwt)
  52. {
  53. $data = $this->splitJwt($jwt);
  54. $header = $this->parseHeader($data[0]);
  55. $claims = $this->parseClaims($data[1]);
  56. $signature = $this->parseSignature($header, $data[2]);
  57. foreach ($claims as $name => $value) {
  58. if (isset($header[$name])) {
  59. $header[$name] = $value;
  60. }
  61. }
  62. if ($signature === null) {
  63. unset($data[2]);
  64. }
  65. return new Token($header, $claims, $signature, $data);
  66. }
  67. /**
  68. * Splits the JWT string into an array
  69. *
  70. * @param string $jwt
  71. *
  72. * @return array
  73. *
  74. * @throws InvalidArgumentException When JWT is not a string or is invalid
  75. */
  76. protected function splitJwt($jwt)
  77. {
  78. if (!is_string($jwt)) {
  79. throw new InvalidArgumentException('The JWT string must have two dots');
  80. }
  81. $data = explode('.', $jwt);
  82. if (count($data) != 3) {
  83. throw new InvalidArgumentException('The JWT string must have two dots');
  84. }
  85. return $data;
  86. }
  87. /**
  88. * Parses the header from a string
  89. *
  90. * @param string $data
  91. *
  92. * @return array
  93. *
  94. * @throws InvalidArgumentException When an invalid header is informed
  95. */
  96. protected function parseHeader($data)
  97. {
  98. $header = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
  99. if (isset($header['enc'])) {
  100. throw new InvalidArgumentException('Encryption is not supported yet');
  101. }
  102. return $header;
  103. }
  104. /**
  105. * Parses the claim set from a string
  106. *
  107. * @param string $data
  108. *
  109. * @return array
  110. */
  111. protected function parseClaims($data)
  112. {
  113. $claims = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
  114. foreach ($claims as $name => &$value) {
  115. $value = $this->claimFactory->create($name, $value);
  116. }
  117. return $claims;
  118. }
  119. /**
  120. * Returns the signature from given data
  121. *
  122. * @param array $header
  123. * @param string $data
  124. *
  125. * @return Signature
  126. */
  127. protected function parseSignature(array $header, $data)
  128. {
  129. if ($data == '' || !isset($header['alg']) || $header['alg'] == 'none') {
  130. return null;
  131. }
  132. $hash = $this->decoder->base64UrlDecode($data);
  133. return new Signature($hash);
  134. }
  135. }