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 Xmf\Key\KeyAbstract;
16:
17: /**
18: * Basic JSON Web Token support
19: *
20: * @category Xmf\Jwt\JsonWebToken
21: * @package Xmf
22: * @author Richard Griffith <richard@geekwright.com>
23: * @copyright 2016 XOOPS Project (http://xoops.org)
24: * @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
25: * @link http://xoops.org
26: */
27: class JsonWebToken
28: {
29: /**
30: * @var KeyAbstract
31: */
32: protected $key;
33:
34: /**
35: * @var string
36: */
37: protected $algorithm = 'HS256';
38:
39: /**
40: * @var array
41: */
42: protected $claims = array();
43:
44: /**
45: * JsonWebToken constructor.
46: *
47: * @param KeyAbstract $key key for signing/validating
48: * @param string $algorithm algorithm to use for signing/validating
49: */
50: public function __construct(KeyAbstract $key, $algorithm = 'HS256')
51: {
52: $this->key = $key;
53: $this->setAlgorithm($algorithm);
54: }
55:
56: /**
57: * @param string $algorithm algorithm to use for signing/validating
58: *
59: * @return JsonWebToken
60: *
61: * @throws \DomainException
62: */
63: public function setAlgorithm($algorithm)
64: {
65: if (array_key_exists($algorithm, JWT::$supported_algs)) {
66: $this->algorithm = $algorithm;
67: return $this;
68: }
69: throw new \DomainException('Algorithm not supported');
70: }
71:
72: /**
73: * Decode a JWT string, validating signature and well defined registered claims,
74: * and optionally validate against a list of supplied claims
75: *
76: * @param string $jwtString string containing the JWT to decode
77: * @param array|\Traversable $assertClaims associative array, claim => value, of claims to assert
78: *
79: * @return object|false
80: */
81: public function decode($jwtString, $assertClaims = array())
82: {
83: $allowedAlgorithms = array($this->algorithm);
84: try {
85: $values = JWT::decode($jwtString, $this->key->getVerifying(), $allowedAlgorithms);
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: } elseif ($values->$claim != $assert) {
94: return false;
95: }
96: }
97: return $values;
98: }
99:
100: /**
101: * Create a signed token string for a payload
102: *
103: * @param array|\ArrayObject $payload traversable set of claims, claim => value
104: * @param int $expirationOffset seconds from now that token will expire. If not specified,
105: * an "exp" claim will not be added or updated
106: *
107: * @return string encoded and signed jwt string
108: *
109: * @throws \DomainException;
110: * @throws \InvalidArgumentException;
111: * @throws \UnexpectedValueException;
112: */
113: public function create($payload, $expirationOffset = 0)
114: {
115: if ((int) $expirationOffset > 0) {
116: $payload['exp'] = time() + (int) $expirationOffset;
117: }
118: $value = JWT::encode($payload, $this->key->getSigning(), $this->algorithm);
119: return $value;
120: }
121: }
122: