Token.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 BadMethodCallException;
  9. use DateTime;
  10. use DateTimeInterface;
  11. use Generator;
  12. use Lcobucci\JWT\Claim\Validatable;
  13. use Lcobucci\JWT\Signer\Key;
  14. use OutOfBoundsException;
  15. /**
  16. * Basic structure of the JWT
  17. *
  18. * @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
  19. * @since 0.1.0
  20. */
  21. class Token
  22. {
  23. /**
  24. * The token headers
  25. *
  26. * @var array
  27. */
  28. private $headers;
  29. /**
  30. * The token claim set
  31. *
  32. * @var array
  33. */
  34. private $claims;
  35. /**
  36. * The token signature
  37. *
  38. * @var Signature
  39. */
  40. private $signature;
  41. /**
  42. * The encoded data
  43. *
  44. * @var array
  45. */
  46. private $payload;
  47. /**
  48. * Initializes the object
  49. *
  50. * @param array $headers
  51. * @param array $claims
  52. * @param array $payload
  53. * @param Signature $signature
  54. */
  55. public function __construct(
  56. array $headers = ['alg' => 'none'],
  57. array $claims = [],
  58. Signature $signature = null,
  59. array $payload = ['', '']
  60. ) {
  61. $this->headers = $headers;
  62. $this->claims = $claims;
  63. $this->signature = $signature;
  64. $this->payload = $payload;
  65. }
  66. /**
  67. * Returns the token headers
  68. *
  69. * @return array
  70. */
  71. public function getHeaders()
  72. {
  73. return $this->headers;
  74. }
  75. /**
  76. * Returns if the header is configured
  77. *
  78. * @param string $name
  79. *
  80. * @return boolean
  81. */
  82. public function hasHeader($name)
  83. {
  84. return array_key_exists($name, $this->headers);
  85. }
  86. /**
  87. * Returns the value of a token header
  88. *
  89. * @param string $name
  90. * @param mixed $default
  91. *
  92. * @return mixed
  93. *
  94. * @throws OutOfBoundsException
  95. */
  96. public function getHeader($name, $default = null)
  97. {
  98. if ($this->hasHeader($name)) {
  99. return $this->getHeaderValue($name);
  100. }
  101. if ($default === null) {
  102. throw new OutOfBoundsException('Requested header is not configured');
  103. }
  104. return $default;
  105. }
  106. /**
  107. * Returns the value stored in header
  108. *
  109. * @param string $name
  110. *
  111. * @return mixed
  112. */
  113. private function getHeaderValue($name)
  114. {
  115. $header = $this->headers[$name];
  116. if ($header instanceof Claim) {
  117. return $header->getValue();
  118. }
  119. return $header;
  120. }
  121. /**
  122. * Returns the token claim set
  123. *
  124. * @return array
  125. */
  126. public function getClaims()
  127. {
  128. return $this->claims;
  129. }
  130. /**
  131. * Returns if the claim is configured
  132. *
  133. * @param string $name
  134. *
  135. * @return boolean
  136. */
  137. public function hasClaim($name)
  138. {
  139. return array_key_exists($name, $this->claims);
  140. }
  141. /**
  142. * Returns the value of a token claim
  143. *
  144. * @param string $name
  145. * @param mixed $default
  146. *
  147. * @return mixed
  148. *
  149. * @throws OutOfBoundsException
  150. */
  151. public function getClaim($name, $default = null)
  152. {
  153. if ($this->hasClaim($name)) {
  154. return $this->claims[$name]->getValue();
  155. }
  156. if ($default === null) {
  157. throw new OutOfBoundsException('Requested claim is not configured');
  158. }
  159. return $default;
  160. }
  161. /**
  162. * Verify if the key matches with the one that created the signature
  163. *
  164. * @param Signer $signer
  165. * @param Key|string $key
  166. *
  167. * @return boolean
  168. *
  169. * @throws BadMethodCallException When token is not signed
  170. */
  171. public function verify(Signer $signer, $key)
  172. {
  173. if ($this->signature === null) {
  174. throw new BadMethodCallException('This token is not signed');
  175. }
  176. if ($this->headers['alg'] !== $signer->getAlgorithmId()) {
  177. return false;
  178. }
  179. return $this->signature->verify($signer, $this->getPayload(), $key);
  180. }
  181. /**
  182. * Validates if the token is valid
  183. *
  184. * @param ValidationData $data
  185. *
  186. * @return boolean
  187. */
  188. public function validate(ValidationData $data)
  189. {
  190. foreach ($this->getValidatableClaims() as $claim) {
  191. if (!$claim->validate($data)) {
  192. return false;
  193. }
  194. }
  195. return true;
  196. }
  197. /**
  198. * Determine if the token is expired.
  199. *
  200. * @param DateTimeInterface $now Defaults to the current time.
  201. *
  202. * @return bool
  203. */
  204. public function isExpired(DateTimeInterface $now = null)
  205. {
  206. $exp = $this->getClaim('exp', false);
  207. if ($exp === false) {
  208. return false;
  209. }
  210. $now = $now ?: new DateTime();
  211. $expiresAt = new DateTime();
  212. $expiresAt->setTimestamp($exp);
  213. return $now > $expiresAt;
  214. }
  215. /**
  216. * Yields the validatable claims
  217. *
  218. * @return Generator
  219. */
  220. private function getValidatableClaims()
  221. {
  222. foreach ($this->claims as $claim) {
  223. if ($claim instanceof Validatable) {
  224. yield $claim;
  225. }
  226. }
  227. }
  228. /**
  229. * Returns the token payload
  230. *
  231. * @return string
  232. */
  233. public function getPayload()
  234. {
  235. return $this->payload[0] . '.' . $this->payload[1];
  236. }
  237. /**
  238. * Returns an encoded representation of the token
  239. *
  240. * @return string
  241. */
  242. public function __toString()
  243. {
  244. $data = implode('.', $this->payload);
  245. if ($this->signature === null) {
  246. $data .= '.';
  247. }
  248. return $data;
  249. }
  250. }