2525 */
2626class JWT
2727{
28- const ASN1_INTEGER = 0x02 ;
29- const ASN1_SEQUENCE = 0x10 ;
30- const ASN1_BIT_STRING = 0x03 ;
28+ // const ASN1_INTEGER = 0x02;
29+ // const ASN1_SEQUENCE = 0x10;
30+ // const ASN1_BIT_STRING = 0x03;
31+ private static $ asn1Integer = 0x02 ;
32+ private static $ asn1Sequence = 0x10 ;
33+ private static $ asn1BitString = 0x03 ;
3134
3235 /**
3336 * When checking nbf, iat or expiration times,
@@ -60,13 +63,11 @@ class JWT
6063 * Decodes a JWT string into a PHP object.
6164 *
6265 * @param string $jwt The JWT
63- * @param Key|array<Key>|mixed $keyOrKeyArray The Key or array of Key objects.
66+ * @param Key|array<Key> $keyOrKeyArray The Key or array of Key objects.
6467 * If the algorithm used is asymmetric, this is the public key
6568 * Each Key object contains an algorithm and matching key.
6669 * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
6770 * 'HS512', 'RS256', 'RS384', and 'RS512'
68- * @param array $allowed_algs [DEPRECATED] List of supported verification algorithms. Only
69- * should be used for backwards compatibility.
7071 *
7172 * @return object The JWT's payload as a PHP object
7273 *
@@ -81,8 +82,9 @@ class JWT
8182 * @uses jsonDecode
8283 * @uses urlsafeB64Decode
8384 */
84- public static function decode ($ jwt , $ keyOrKeyArray, array $ allowed_algs = array () )
85+ public static function decode ($ jwt , $ keyOrKeyArray )
8586 {
87+ // Validate JWT
8688 $ timestamp = \is_null (static ::$ timestamp ) ? \time () : static ::$ timestamp ;
8789
8890 if (empty ($ keyOrKeyArray )) {
@@ -109,31 +111,18 @@ public static function decode($jwt, $keyOrKeyArray, array $allowed_algs = array(
109111 throw new UnexpectedValueException ('Algorithm not supported ' );
110112 }
111113
112- list ($ keyMaterial , $ algorithm ) = self ::getKeyMaterialAndAlgorithm (
113- $ keyOrKeyArray ,
114- empty ($ header ->kid ) ? null : $ header ->kid
115- );
114+ $ key = self ::getKey ($ keyOrKeyArray , empty ($ header ->kid ) ? null : $ header ->kid );
116115
117- if (empty ($ algorithm )) {
118- // Use deprecated "allowed_algs" to determine if the algorithm is supported.
119- // This opens up the possibility of an attack in some implementations.
120- // @see https://github.com/firebase/php-jwt/issues/351
121- if (!\in_array ($ header ->alg , $ allowed_algs )) {
122- throw new UnexpectedValueException ('Algorithm not allowed ' );
123- }
124- } else {
125- // Check the algorithm
126- if (!self ::constantTimeEquals ($ algorithm , $ header ->alg )) {
127- // See issue #351
128- throw new UnexpectedValueException ('Incorrect key for this algorithm ' );
129- }
116+ // Check the algorithm
117+ if (!self ::constantTimeEquals ($ key ->getAlgorithm (), $ header ->alg )) {
118+ // See issue #351
119+ throw new UnexpectedValueException ('Incorrect key for this algorithm ' );
130120 }
131121 if ($ header ->alg === 'ES256 ' || $ header ->alg === 'ES384 ' ) {
132122 // OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures
133123 $ sig = self ::signatureToDER ($ sig );
134124 }
135-
136- if (!static ::verify ("$ headb64. $ bodyb64 " , $ sig , $ keyMaterial , $ header ->alg )) {
125+ if (!static ::verify ("$ headb64. $ bodyb64 " , $ sig , $ key ->getKeyMaterial (), $ header ->alg )) {
137126 throw new SignatureInvalidException ('Signature verification failed ' );
138127 }
139128
@@ -179,7 +168,7 @@ public static function decode($jwt, $keyOrKeyArray, array $allowed_algs = array(
179168 * @uses jsonEncode
180169 * @uses urlsafeB64Encode
181170 */
182- public static function encode ($ payload , $ key , $ alg = ' HS256 ' , $ keyId = null , $ head = null )
171+ public static function encode ($ payload , $ key , $ alg , $ keyId = null , $ head = null )
183172 {
184173 $ header = array ('typ ' => 'JWT ' , 'alg ' => $ alg );
185174 if ($ keyId !== null ) {
@@ -212,7 +201,7 @@ public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $he
212201 *
213202 * @throws DomainException Unsupported algorithm or bad key was specified
214203 */
215- public static function sign ($ msg , $ key , $ alg = ' HS256 ' )
204+ public static function sign ($ msg , $ key , $ alg )
216205 {
217206 if (empty (static ::$ supported_algs [$ alg ])) {
218207 throw new DomainException ('Algorithm not supported ' );
@@ -345,7 +334,12 @@ public static function jsonDecode($input)
345334 */
346335 public static function jsonEncode ($ input )
347336 {
348- $ json = \json_encode ($ input );
337+ if (PHP_VERSION_ID >= 50400 ) {
338+ $ json = \json_encode ($ input , \JSON_UNESCAPED_SLASHES );
339+ } else {
340+ // PHP 5.3 only
341+ $ json = \json_encode ($ input );
342+ }
349343 if ($ errno = \json_last_error ()) {
350344 static ::handleJsonError ($ errno );
351345 } elseif ($ json === 'null ' && $ input !== null ) {
@@ -394,40 +388,34 @@ public static function urlsafeB64Encode($input)
394388 *
395389 * @return array containing the keyMaterial and algorithm
396390 */
397- private static function getKeyMaterialAndAlgorithm ($ keyOrKeyArray , $ kid = null )
391+ private static function getKey ($ keyOrKeyArray , $ kid = null )
398392 {
399- if (
400- is_string ($ keyOrKeyArray )
401- || is_resource ($ keyOrKeyArray )
402- || $ keyOrKeyArray instanceof OpenSSLAsymmetricKey
403- ) {
404- return array ($ keyOrKeyArray , null );
405- }
406-
407393 if ($ keyOrKeyArray instanceof Key) {
408- return array ( $ keyOrKeyArray-> getKeyMaterial (), $ keyOrKeyArray -> getAlgorithm ()) ;
394+ return $ keyOrKeyArray ;
409395 }
410396
411397 if (is_array ($ keyOrKeyArray ) || $ keyOrKeyArray instanceof ArrayAccess) {
398+ foreach ($ keyOrKeyArray as $ keyId => $ key ) {
399+ if (!$ key instanceof Key) {
400+ throw new UnexpectedValueException (
401+ '$keyOrKeyArray must be an instance of Firebase\JWT\Key key or an '
402+ . 'array of Firebase\JWT\Key keys '
403+ );
404+ }
405+ }
412406 if (!isset ($ kid )) {
413407 throw new UnexpectedValueException ('"kid" empty, unable to lookup correct key ' );
414408 }
415409 if (!isset ($ keyOrKeyArray [$ kid ])) {
416410 throw new UnexpectedValueException ('"kid" invalid, unable to lookup correct key ' );
417411 }
418412
419- $ key = $ keyOrKeyArray [$ kid ];
420-
421- if ($ key instanceof Key) {
422- return array ($ key ->getKeyMaterial (), $ key ->getAlgorithm ());
423- }
424-
425- return array ($ key , null );
413+ return $ keyOrKeyArray [$ kid ];
426414 }
427415
428416 throw new UnexpectedValueException (
429- '$keyOrKeyArray must be a string|resource key, an array of string|resource keys, '
430- . 'an instance of Firebase\JWT\Key key or an array of Firebase\JWT\Key keys '
417+ '$keyOrKeyArray must be an instance of Firebase\JWT\Key key or an '
418+ . 'array of Firebase\JWT\Key keys '
431419 );
432420 }
433421
@@ -515,9 +503,9 @@ private static function signatureToDER($sig)
515503 }
516504
517505 return self ::encodeDER (
518- self ::ASN1_SEQUENCE ,
519- self ::encodeDER (self ::ASN1_INTEGER , $ r ) .
520- self ::encodeDER (self ::ASN1_INTEGER , $ s )
506+ self ::$ asn1Sequence ,
507+ self ::encodeDER (self ::$ asn1Integer , $ r ) .
508+ self ::encodeDER (self ::$ asn1Integer , $ s )
521509 );
522510 }
523511
@@ -531,7 +519,7 @@ private static function signatureToDER($sig)
531519 private static function encodeDER ($ type , $ value )
532520 {
533521 $ tag_header = 0 ;
534- if ($ type === self ::ASN1_SEQUENCE ) {
522+ if ($ type === self ::$ asn1Sequence ) {
535523 $ tag_header |= 0x20 ;
536524 }
537525
@@ -596,7 +584,7 @@ private static function readDER($der, $offset = 0)
596584 }
597585
598586 // Value
599- if ($ type == self ::ASN1_BIT_STRING ) {
587+ if ($ type == self ::$ asn1BitString ) {
600588 $ pos ++; // Skip the first contents octet (padding indicator)
601589 $ data = \substr ($ der , $ pos , $ len - 1 );
602590 $ pos += $ len - 1 ;
0 commit comments