1: | <?php |
2: | /* |
3: | You may not change or alter any portion of this comment or credits |
4: | of supporting developers from this source code or any supporting source code |
5: | which is considered copyrighted (c) material of the original comment or credit authors. |
6: | |
7: | This program is distributed in the hope that it will be useful, |
8: | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9: | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
10: | */ |
11: | |
12: | namespace Xmf\Jwt; |
13: | |
14: | use Firebase\JWT\JWT; |
15: | use Firebase\JWT\Key; |
16: | use Xmf\Key\KeyAbstract; |
17: | |
18: | /** |
19: | * Basic JSON Web Token support |
20: | * |
21: | * @category Xmf\Jwt\JsonWebToken |
22: | * @package Xmf |
23: | * @author Richard Griffith <richard@geekwright.com> |
24: | * @copyright 2018-2023 XOOPS Project (https://xoops.org) |
25: | * @license GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html) |
26: | * @link https://xoops.org |
27: | */ |
28: | class JsonWebToken |
29: | { |
30: | /** |
31: | * @var KeyAbstract |
32: | */ |
33: | protected $key; |
34: | |
35: | /** |
36: | * @var string |
37: | */ |
38: | protected $algorithm = 'HS256'; |
39: | |
40: | /** |
41: | * @var array |
42: | */ |
43: | protected $claims = array(); |
44: | |
45: | /** |
46: | * JsonWebToken constructor. |
47: | * |
48: | * @param KeyAbstract $key key for signing/validating |
49: | * @param string $algorithm algorithm to use for signing/validating |
50: | */ |
51: | public function __construct(KeyAbstract $key, $algorithm = 'HS256') |
52: | { |
53: | $this->key = $key; |
54: | $this->setAlgorithm($algorithm); |
55: | } |
56: | |
57: | /** |
58: | * @param string $algorithm algorithm to use for signing/validating |
59: | * |
60: | * @return JsonWebToken |
61: | * |
62: | * @throws \DomainException |
63: | */ |
64: | public function setAlgorithm($algorithm) |
65: | { |
66: | if (array_key_exists($algorithm, JWT::$supported_algs)) { |
67: | $this->algorithm = $algorithm; |
68: | return $this; |
69: | } |
70: | throw new \DomainException('Algorithm not supported'); |
71: | } |
72: | |
73: | /** |
74: | * Decode a JWT string, validating signature and well defined registered claims, |
75: | * and optionally validate against a list of supplied claims |
76: | * |
77: | * @param string $jwtString string containing the JWT to decode |
78: | * @param array|\Traversable $assertClaims associative array, claim => value, of claims to assert |
79: | * |
80: | * @return object|false |
81: | */ |
82: | public function decode($jwtString, $assertClaims = array()) |
83: | { |
84: | try { |
85: | $values = JWT::decode($jwtString, new Key($this->key->getVerifying(), $this->algorithm)); |
86: | } catch (\Exception $e) { |
87: | trigger_error($e->getMessage(), E_USER_NOTICE); |
88: | return false; |
89: | } |
90: | foreach ($assertClaims as $claim => $assert) { |
91: | if (!property_exists($values, $claim)) { |
92: | return false; |
93: | } |
94: | |
95: | if ($values->$claim != $assert) { |
96: | return false; |
97: | } |
98: | } |
99: | return $values; |
100: | } |
101: | |
102: | /** |
103: | * Create a signed token string for a payload |
104: | * |
105: | * @param array|\ArrayObject $payload traversable set of claims, claim => value |
106: | * @param int $expirationOffset seconds from now that token will expire. If not specified, |
107: | * an "exp" claim will not be added or updated |
108: | * |
109: | * @return string encoded and signed jwt string |
110: | * |
111: | * @throws \DomainException; |
112: | * @throws \InvalidArgumentException; |
113: | * @throws \UnexpectedValueException; |
114: | */ |
115: | public function create($payload, $expirationOffset = 0) |
116: | { |
117: | if ((int) $expirationOffset > 0) { |
118: | $payload['exp'] = time() + (int) $expirationOffset; |
119: | } |
120: | $value = JWT::encode($payload, $this->key->getSigning(), $this->algorithm); |
121: | return $value; |
122: | } |
123: | } |
124: |