Skip to content

Commit 500c19f

Browse files
committed
bug fix
1 parent a3f1237 commit 500c19f

File tree

4 files changed

+178
-22
lines changed

4 files changed

+178
-22
lines changed

README.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,157 @@ $decoded_token = jwt_decode($token, $publicKey, ['algorithm' => 'ES256']);
155155
print_r($decoded_token);
156156
```
157157

158+
## Support for reserved claim names
159+
160+
JSON Web Token defines some reserved claim names and defines how they should be used. JWT supports these reserved claim names:
161+
162+
- 'exp' (Expiration Time) Claim
163+
- 'nbf' (Not Before Time) Claim
164+
- 'iss' (Issuer) Claim
165+
- 'aud' (Audience) Claim
166+
- 'jti' (JWT ID) Claim
167+
- 'iat' (Issued At) Claim
168+
- 'sub' (Subject) Claim
169+
170+
### Expiration Time Claim
171+
172+
> The `exp` (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the `exp` claim requires that the current date/time MUST be before the expiration date/time listed in the `exp` claim. Implementers MAY provide for some small `leeway`, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a **NumericDate** value. Use of this claim is OPTIONAL.
173+
174+
#### Handle Expiration Claim
175+
176+
```php
177+
$payload = ['data' => 'data', 'exp' => time() + 4 * 3600];
178+
179+
$token = jwt_encode($payload, $hmackey, 'HS256');
180+
181+
try {
182+
$decoded_token = jwt_decode($token, $hmackey, ['algorithm' => 'HS256']);
183+
} catch (Exception $e) {
184+
// Expired token
185+
$e->getMessage();
186+
}
187+
```
188+
189+
#### Adding Leeway
190+
191+
```php
192+
$payload = ['data' => 'data', 'exp' => time() - 10];
193+
194+
// build expired token
195+
$token = jwt_encode($payload, $hmackey, 'HS256');
196+
197+
try {
198+
$decoded_token = jwt_decode($token, $hmackey, ['leeway' => 30, 'algorithm' => 'HS256']);
199+
} catch (Exception $e) {
200+
// Expired token
201+
}
202+
```
203+
204+
### Not Before Time Claim
205+
206+
> The `nbf` (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the `nbf` claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the `nbf` claim. Implementers MAY provide for some small `leeway`, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a **NumericDate** value. Use of this claim is OPTIONAL.
207+
208+
#### Handle Not Before Claim
209+
210+
```php
211+
$payload = ['data' => 'data', 'nbf' => time() - 3600];
212+
213+
$token = jwt_encode($payload, $hmackey, 'HS256');
214+
215+
try {
216+
$decoded_token = jwt_decode($token, $hmackey, ['algorithm' => 'HS256']);
217+
} catch (Exception $e) {
218+
// Handle invalid token
219+
}
220+
```
221+
222+
#### Adding Leeway
223+
224+
```php
225+
$payload = ['data' => 'data', 'nbf' => time() + 10];
226+
227+
// build expired token
228+
$token = jwt_encode($payload, $hmackey, 'HS256');
229+
230+
try {
231+
$decoded_token = jwt_decode($token, $hmackey, ['leeway' => 30, 'algorithm' => 'HS256']);
232+
} catch (Exception $e) {
233+
// Handle invalid token
234+
}
235+
```
236+
237+
### Issuer Claim
238+
239+
> The `iss` (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The `iss` value is a case-sensitive string containing a **StringOrURI** value. Use of this claim is OPTIONAL.
240+
241+
```php
242+
$payload = ['data' => 'data', 'iss' => 'http://example.org'];
243+
244+
$token = jwt_encode($payload, $hmackey, 'HS256');
245+
246+
try {
247+
$decoded_token = jwt_decode($token, $hmackey, ['iss' => 'http://example.org', 'algorithm' => 'HS256']);
248+
} catch (Exception $e) {
249+
// Handle invalid token
250+
}
251+
```
252+
253+
### Audience Claim
254+
255+
```php
256+
$payload = ['data' => 'data', 'aud' => 'Young Man'];
257+
258+
$token = jwt_encode($payload, $hmackey, 'HS256');
259+
260+
try {
261+
$decoded_token = jwt_decode($token, $hmackey, ['iss' => 'Young Man', 'algorithm' => 'HS256']);
262+
} catch (Exception $e) {
263+
// Handle invalid token
264+
}
265+
```
266+
267+
### JWT ID Claim
268+
269+
```php
270+
$payload = ['data' => 'data', 'jti' => md5('id')];
271+
272+
$token = jwt_encode($payload, $hmackey, 'HS256');
273+
274+
try {
275+
$decoded_token = jwt_decode($token, $hmackey, ['jti' => md5('id'), 'algorithm' => 'HS256']);
276+
} catch (Exception $e) {
277+
// Handle invalid token
278+
}
279+
```
280+
281+
### Issued At Claim
282+
283+
```php
284+
$payload = ['data' => 'data', 'iat' => time()];
285+
286+
$token = jwt_encode($payload, $hmackey, 'HS256');
287+
288+
try {
289+
$decoded_token = jwt_decode($token, $hmackey, ['algorithm' => 'HS256']);
290+
} catch (Exception $e) {
291+
// Handle invalid token
292+
}
293+
```
294+
295+
### Subject Claim
296+
297+
```php
298+
$payload = ['data' => 'data', 'sub' => 'Subject'];
299+
300+
$token = jwt_encode($payload, $hmackey, 'HS256');
301+
302+
try {
303+
$decoded_token = jwt_decode($token, $hmackey, ['sub' => 'Subject', 'algorithm' => 'HS256']);
304+
} catch (Exception $e) {
305+
// Handle invalid token
306+
}
307+
```
308+
158309
## Benchmarks
159310

160311
![Benchmarks](https://cdoco.com/images/jwt-benchmarks.png "Benchmarks")

jwt.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,21 @@ char *jwt_hash_str_find_str(zval *arr, char *key)
235235
return str;
236236
}
237237

238+
long jwt_hash_str_find_long(zval *arr, char *key)
239+
{
240+
zval *zv = zend_hash_str_find(Z_ARRVAL_P(arr), key, strlen(key));
241+
242+
if (zv != NULL) {
243+
return Z_LVAL_P(zv);
244+
}
245+
246+
return 0;
247+
}
248+
238249
int jwt_verify_claims(zval *arr, char *key, char *str)
239250
{
240-
if (strcmp(jwt_hash_str_find_str(arr, key), str)) {
251+
char *rs = jwt_hash_str_find_str(arr, key);
252+
if (rs && strcmp(rs, str)) {
241253
return FAILURE;
242254
}
243255

@@ -272,8 +284,14 @@ int jwt_verify_body(char *body, zval *return_value)
272284
err_msg = "Iss verify fail";
273285

274286
/* iat */
275-
if (jwt_options->iat && jwt_verify_claims(return_value, "iat", jwt_options->iat))
276-
err_msg = "Iat verify fail";
287+
if (jwt_options->iat && jwt_options->iat > (curr_time + jwt_options->leeway)) {
288+
struct tm *timeinfo;
289+
char buf[128];
290+
291+
timeinfo = localtime(&curr_time);
292+
strftime(buf, sizeof(buf), "Cannot handle token prior to %Y-%m-%d %H:%M:%S", timeinfo);
293+
err_msg = buf;
294+
}
277295

278296
/* jti */
279297
if (jwt_options->jti && jwt_verify_claims(return_value, "jti", jwt_options->jti))
@@ -308,15 +326,9 @@ int jwt_parse_options(zval *options)
308326
jwt_options->algorithm = alg;
309327
}
310328

311-
/* leeway */
312-
zval *zv_leeway = zend_hash_str_find(Z_ARRVAL_P(options), "leeway", strlen("leeway"));
313-
if (zv_leeway != NULL) {
314-
jwt_options->leeway = Z_LVAL_P(zv_leeway);
315-
}
316-
317329
/* options */
330+
jwt_options->leeway = jwt_hash_str_find_long(options, "leeway");
318331
jwt_options->iss = jwt_hash_str_find_str(options, "iss");
319-
jwt_options->iat = jwt_hash_str_find_str(options, "iat");
320332
jwt_options->jti = jwt_hash_str_find_str(options, "jti");
321333
jwt_options->aud = jwt_hash_str_find_str(options, "aud");
322334
jwt_options->sub = jwt_hash_str_find_str(options, "sub");
@@ -361,15 +373,9 @@ PHP_FUNCTION(jwt_encode)
361373
}
362374

363375
/* set expiration and not before */
364-
zval *zv_exp = zend_hash_str_find(Z_ARRVAL_P(claims), "exp", 3);
365-
if (zv_exp) {
366-
jwt_options->expiration = Z_LVAL_P(zv_exp);
367-
}
368-
369-
zval *zv_nbf = zend_hash_str_find(Z_ARRVAL_P(claims), "nbf", 3);
370-
if (zv_nbf) {
371-
jwt_options->not_before = Z_LVAL_P(zv_nbf);
372-
}
376+
jwt_options->expiration = jwt_hash_str_find_long(claims, "exp");
377+
jwt_options->not_before = jwt_hash_str_find_long(claims, "nbf");
378+
jwt_options->iat = jwt_hash_str_find_long(claims, "iat");
373379

374380
/* init */
375381
array_init(&header);

jwt.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
"name" => "ZiHang Gao",
1212
"admin" => true
1313
],
14-
"iss" => "http://example.org",
1514
"sub" => "1234567890",
1615
"nbf" => time() + 10
1716
);
@@ -20,4 +19,4 @@
2019
$token = jwt_encode($claims, $key);
2120

2221
echo $token . PHP_EOL;
23-
print_r(jwt_decode($token, $key, ['leeway' => 1, "iss" => "http://example.org"]));
22+
print_r(jwt_decode($token, $key, ['leeway' => 20, "iss" => "http://example.org"]));

php_jwt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ typedef struct options {
5959
time_t expiration;
6060
time_t not_before;
6161
char *iss;
62-
char *iat;
62+
time_t iat;
6363
char *jti;
6464
char *aud;
6565
char *sub;

0 commit comments

Comments
 (0)