Skip to content

Commit 37a6b73

Browse files
committed
Merge pull request #60 from sjones608/nullkey
require a non-empty key to decode a JWT
2 parents 11855db + 17180b1 commit 37a6b73

File tree

2 files changed

+63
-40
lines changed

2 files changed

+63
-40
lines changed

src/JWT.php

+43-40
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Firebase\JWT;
44
use \DomainException;
5+
use \InvalidArgumentException;
56
use \UnexpectedValueException;
67
use \DateTime;
78

@@ -56,8 +57,11 @@ class JWT
5657
* @uses jsonDecode
5758
* @uses urlsafeB64Decode
5859
*/
59-
public static function decode($jwt, $key = null, $allowed_algs = array())
60+
public static function decode($jwt, $key, $allowed_algs = array())
6061
{
62+
if (empty($key)) {
63+
throw new InvalidArgumentException('Key may not be empty');
64+
}
6165
$tks = explode('.', $jwt);
6266
if (count($tks) != 3) {
6367
throw new UnexpectedValueException('Wrong number of segments');
@@ -70,50 +74,49 @@ public static function decode($jwt, $key = null, $allowed_algs = array())
7074
throw new UnexpectedValueException('Invalid claims encoding');
7175
}
7276
$sig = JWT::urlsafeB64Decode($cryptob64);
73-
if (isset($key)) {
74-
if (empty($header->alg)) {
75-
throw new DomainException('Empty algorithm');
76-
}
77-
if (empty(self::$supported_algs[$header->alg])) {
78-
throw new DomainException('Algorithm not supported');
79-
}
80-
if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
81-
throw new DomainException('Algorithm not allowed');
82-
}
83-
if (is_array($key) || $key instanceof \ArrayAccess) {
84-
if (isset($header->kid)) {
85-
$key = $key[$header->kid];
86-
} else {
87-
throw new DomainException('"kid" empty, unable to lookup correct key');
88-
}
77+
78+
if (empty($header->alg)) {
79+
throw new DomainException('Empty algorithm');
80+
}
81+
if (empty(self::$supported_algs[$header->alg])) {
82+
throw new DomainException('Algorithm not supported');
83+
}
84+
if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
85+
throw new DomainException('Algorithm not allowed');
86+
}
87+
if (is_array($key) || $key instanceof \ArrayAccess) {
88+
if (isset($header->kid)) {
89+
$key = $key[$header->kid];
90+
} else {
91+
throw new DomainException('"kid" empty, unable to lookup correct key');
8992
}
93+
}
9094

91-
// Check the signature
92-
if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
93-
throw new SignatureInvalidException('Signature verification failed');
94-
}
95+
// Check the signature
96+
if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
97+
throw new SignatureInvalidException('Signature verification failed');
98+
}
9599

96-
// Check if the nbf if it is defined. This is the time that the
97-
// token can actually be used. If it's not yet that time, abort.
98-
if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) {
99-
throw new BeforeValidException(
100-
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
101-
);
102-
}
100+
// Check if the nbf if it is defined. This is the time that the
101+
// token can actually be used. If it's not yet that time, abort.
102+
if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) {
103+
throw new BeforeValidException(
104+
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
105+
);
106+
}
103107

104-
// Check that this token has been created before 'now'. This prevents
105-
// using tokens that have been created for later use (and haven't
106-
// correctly used the nbf claim).
107-
if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) {
108-
throw new BeforeValidException(
109-
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
110-
);
111-
}
108+
// Check that this token has been created before 'now'. This prevents
109+
// using tokens that have been created for later use (and haven't
110+
// correctly used the nbf claim).
111+
if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) {
112+
throw new BeforeValidException(
113+
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
114+
);
115+
}
112116

113-
// Check if this token has expired.
114-
if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) {
115-
throw new ExpiredException('Expired token');
116-
}
117+
// Check if this token has expired.
118+
if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) {
119+
throw new ExpiredException('Expired token');
117120
}
118121

119122
return $payload;

tests/JWTTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,26 @@ public function testInvalidToken()
181181
$decoded = JWT::decode($encoded, 'my_key2', array('HS256'));
182182
}
183183

184+
public function testNullKeyFails()
185+
{
186+
$payload = array(
187+
"message" => "abc",
188+
"exp" => time() + JWT::$leeway + 20); // time in the future
189+
$encoded = JWT::encode($payload, 'my_key');
190+
$this->setExpectedException('InvalidArgumentException');
191+
$decoded = JWT::decode($encoded, null, array('HS256'));
192+
}
193+
194+
public function testEmptyKeyFails()
195+
{
196+
$payload = array(
197+
"message" => "abc",
198+
"exp" => time() + JWT::$leeway + 20); // time in the future
199+
$encoded = JWT::encode($payload, 'my_key');
200+
$this->setExpectedException('InvalidArgumentException');
201+
$decoded = JWT::decode($encoded, '', array('HS256'));
202+
}
203+
184204
public function testRSEncodeDecode()
185205
{
186206
$privKey = openssl_pkey_new(array('digest_alg' => 'sha256',

0 commit comments

Comments
 (0)