Skip to content

Commit 49f7de6

Browse files
committed
require a non-empty key to decode a JWT
1 parent 21498f7 commit 49f7de6

File tree

2 files changed

+62
-40
lines changed

2 files changed

+62
-40
lines changed

Authentication/JWT.php

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ class JWT
4949
* @uses jsonDecode
5050
* @uses urlsafeB64Decode
5151
*/
52-
public static function decode($jwt, $key = null, $allowed_algs = array())
52+
public static function decode($jwt, $key, $allowed_algs = array())
5353
{
54+
if (empty($key)) {
55+
throw new InvalidArgumentException('Key may not be empty');
56+
}
5457
$tks = explode('.', $jwt);
5558
if (count($tks) != 3) {
5659
throw new UnexpectedValueException('Wrong number of segments');
@@ -63,50 +66,49 @@ public static function decode($jwt, $key = null, $allowed_algs = array())
6366
throw new UnexpectedValueException('Invalid claims encoding');
6467
}
6568
$sig = JWT::urlsafeB64Decode($cryptob64);
66-
if (isset($key)) {
67-
if (empty($header->alg)) {
68-
throw new DomainException('Empty algorithm');
69-
}
70-
if (empty(self::$supported_algs[$header->alg])) {
71-
throw new DomainException('Algorithm not supported');
72-
}
73-
if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
74-
throw new DomainException('Algorithm not allowed');
75-
}
76-
if (is_array($key) || $key instanceof \ArrayAccess) {
77-
if (isset($header->kid)) {
78-
$key = $key[$header->kid];
79-
} else {
80-
throw new DomainException('"kid" empty, unable to lookup correct key');
81-
}
69+
70+
if (empty($header->alg)) {
71+
throw new DomainException('Empty algorithm');
72+
}
73+
if (empty(self::$supported_algs[$header->alg])) {
74+
throw new DomainException('Algorithm not supported');
75+
}
76+
if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
77+
throw new DomainException('Algorithm not allowed');
78+
}
79+
if (is_array($key) || $key instanceof \ArrayAccess) {
80+
if (isset($header->kid)) {
81+
$key = $key[$header->kid];
82+
} else {
83+
throw new DomainException('"kid" empty, unable to lookup correct key');
8284
}
85+
}
8386

84-
// Check the signature
85-
if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
86-
throw new SignatureInvalidException('Signature verification failed');
87-
}
87+
// Check the signature
88+
if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
89+
throw new SignatureInvalidException('Signature verification failed');
90+
}
8891

89-
// Check if the nbf if it is defined. This is the time that the
90-
// token can actually be used. If it's not yet that time, abort.
91-
if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) {
92-
throw new BeforeValidException(
93-
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
94-
);
95-
}
92+
// Check if the nbf if it is defined. This is the time that the
93+
// token can actually be used. If it's not yet that time, abort.
94+
if (isset($payload->nbf) && $payload->nbf > (time() + self::$leeway)) {
95+
throw new BeforeValidException(
96+
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
97+
);
98+
}
9699

97-
// Check that this token has been created before 'now'. This prevents
98-
// using tokens that have been created for later use (and haven't
99-
// correctly used the nbf claim).
100-
if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) {
101-
throw new BeforeValidException(
102-
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
103-
);
104-
}
100+
// Check that this token has been created before 'now'. This prevents
101+
// using tokens that have been created for later use (and haven't
102+
// correctly used the nbf claim).
103+
if (isset($payload->iat) && $payload->iat > (time() + self::$leeway)) {
104+
throw new BeforeValidException(
105+
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
106+
);
107+
}
105108

106-
// Check if this token has expired.
107-
if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) {
108-
throw new ExpiredException('Expired token');
109-
}
109+
// Check if this token has expired.
110+
if (isset($payload->exp) && (time() - self::$leeway) >= $payload->exp) {
111+
throw new ExpiredException('Expired token');
110112
}
111113

112114
return $payload;

tests/JWTTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,26 @@ public function testInvalidToken()
180180
$decoded = JWT::decode($encoded, 'my_key2', array('HS256'));
181181
}
182182

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

0 commit comments

Comments
 (0)