@@ -32,32 +32,12 @@ class JWT
32
32
'HS384 ' => array ('hash_hmac ' , 'SHA384 ' ),
33
33
'RS256 ' => array ('openssl ' , 'SHA256 ' ),
34
34
);
35
- /**
36
- * Returns just the header portion of the jwt. This allows
37
- * you to determine which key should be used to verify
38
- * the jwt, using the "kid" field
39
- *
40
- * @param string $jwt
41
- *
42
- * @return object The JWT's header object, with fields "typ","alg", and optionally "kid"
43
- */
44
- public static function decodeHeader ($ jwt ) {
45
- $ tks = explode ('. ' , $ jwt );
46
- if (count ($ tks ) != 3 ) {
47
- throw new UnexpectedValueException ('Wrong number of segments ' );
48
- }
49
- list ($ headb64 , $ bodyb64 , $ cryptob64 ) = $ tks ;
50
- if (null === ($ header = JWT ::jsonDecode (JWT ::urlsafeB64Decode ($ headb64 )))) {
51
- throw new UnexpectedValueException ('Invalid segment encoding ' );
52
- }
53
- return $ header ;
54
- }
55
35
56
36
/**
57
37
* Decodes a JWT string into a PHP object.
58
38
*
59
39
* @param string $jwt The JWT
60
- * @param string|null $key The secret key
40
+ * @param string|Array| null $key The secret key, or map of keys
61
41
* @param bool $verify Don't skip verification process
62
42
*
63
43
* @return object The JWT's payload as a PHP object
@@ -85,6 +65,11 @@ public static function decode($jwt, $key = null, $verify = true)
85
65
if (empty ($ header ->alg )) {
86
66
throw new DomainException ('Empty algorithm ' );
87
67
}
68
+ if (is_array ($ key ) && !isset ($ header ->kid )) {
69
+ throw new DomainException ('"kid" empty, unable to lookup correct key ' );
70
+ } elseif (is_array ($ key ) && isset ($ header ->kid )) {
71
+ $ key = $ key [$ header ->kid ];
72
+ }
88
73
if (!JWT ::verify ("$ headb64. $ bodyb64 " , $ sig , $ key , $ header ->alg )) {
89
74
throw new UnexpectedValueException ('Signature verification failed ' );
90
75
}
@@ -108,10 +93,12 @@ public static function decode($jwt, $key = null, $verify = true)
108
93
* @uses jsonEncode
109
94
* @uses urlsafeB64Encode
110
95
*/
111
- public static function encode ($ payload , $ key , $ algo = 'HS256 ' )
96
+ public static function encode ($ payload , $ key , $ algo = 'HS256 ' , $ keyId = null )
112
97
{
113
98
$ header = array ('typ ' => 'JWT ' , 'alg ' => $ algo );
114
-
99
+ if ($ keyId !== null ) {
100
+ $ header ['kid ' ] = $ keyId ;
101
+ }
115
102
$ segments = array ();
116
103
$ segments [] = JWT ::urlsafeB64Encode (JWT ::jsonEncode ($ header ));
117
104
$ segments [] = JWT ::urlsafeB64Encode (JWT ::jsonEncode ($ payload ));
@@ -127,7 +114,7 @@ public static function encode($payload, $key, $algo = 'HS256')
127
114
* Sign a string with a given key and algorithm.
128
115
*
129
116
* @param string $msg The message to sign
130
- * @param string $key The secret key
117
+ * @param string|resource $key The secret key
131
118
* @param string $method The signing algorithm. Supported
132
119
* algorithms are 'HS256', 'HS384' and 'HS512'
133
120
*
@@ -154,6 +141,16 @@ public static function sign($msg, $key, $method = 'HS256')
154
141
}
155
142
}
156
143
144
+ /**
145
+ * Verify a signature with the mesage, key and method. Not all methods
146
+ * are symmetric, so we must have a separate verify and sign method.
147
+ * @param string $msg the original message
148
+ * @param string $signature
149
+ * @param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public key
150
+ * @param string $method
151
+ * @return bool
152
+ * @throws DomainException Invalid Algorithm or OpenSSL failure
153
+ */
157
154
public static function verify ($ msg , $ signature , $ key , $ method = 'HS256 ' ) {
158
155
if (empty (self ::$ methods [$ method ])) {
159
156
throw new DomainException ('Algorithm not supported ' );
@@ -163,7 +160,7 @@ public static function verify($msg, $signature, $key, $method = 'HS256') {
163
160
case 'openssl ' :
164
161
$ success = openssl_verify ($ msg , $ signature , $ key , $ algo );
165
162
if (!$ success ) {
166
- throw new DomainException ("OpenSSL unable to sign data " );
163
+ throw new DomainException ("OpenSSL unable to verify data: " . openssl_error_string () );
167
164
} else {
168
165
return $ signature ;
169
166
}
0 commit comments