Skip to content

Commit b012ac1

Browse files
authored
Merge pull request #3 from cdoco/develop
Add a number of features
2 parents fa924ab + 761791f commit b012ac1

17 files changed

+690
-88
lines changed

README.md

+286-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div align="center">
22
<p><img src="https://jwt.io/img/logo-asset.svg" /></p>
3-
<p>A PHP extension for JSON Web Token (JWT)</p>
3+
<p>A PHP extension for <a target="_blank" href="https://tools.ietf.org/html/rfc7519">RFC 7519 OAuth JSON Web Token (JWT)</a></p>
44
<a target="_blank" href="https://travis-ci.org/cdoco/php-jwt" title="Build Status"><img src="https://travis-ci.org/cdoco/php-jwt.svg"></a>
55
<img src="https://img.shields.io/badge/branch-master-brightgreen.svg?style=flat-square">
66
</div>
@@ -23,8 +23,8 @@ $ make && make install
2323
## Quick Example
2424

2525
```php
26-
$key = "example_key";
27-
$claims = array(
26+
$key = "example-hmac-key";
27+
$payload = array(
2828
"data" => [
2929
"name" => "ZiHang Gao",
3030
"admin" => true
@@ -34,43 +34,298 @@ $claims = array(
3434
);
3535

3636
// default HS256 algorithm
37-
$token = jwt_encode($claims, $key);
37+
$token = jwt_encode($payload, $key);
3838

39-
echo $token . PHP_EOL;
40-
//eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
41-
//eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiWmlIYW5nIEdhbyIsImFkbWluIjp0cnVlfQ.
42-
//2lFeBTsRegsjXiBCZNkW41KFlsZPSFu7KTsyAM9lUiQ
39+
//eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7Im5hbWUiOiJaaUhhbmcgR2FvIiwiYWRtaW4iOnRydWV9LCJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsInN1YiI6IjEyMzQ1Njc4OTAifQ.UcrCt9o9rz38kKMTa-nCrm7JNQRNAId5Xg9C7EIl2Zc
40+
echo $token;
4341

44-
print_r(jwt_decode($token, $key));
45-
/**
46-
Array
47-
(
48-
[data] => Array
49-
(
50-
[name] => ZiHang Gao
51-
[admin] => 1
52-
)
42+
$decoded_token = jwt_decode($token, $key);
5343

54-
[iss] => http://example.org
55-
[sub] => 1234567890
56-
)
57-
*/
44+
// Array
45+
// (
46+
// [data] => Array
47+
// (
48+
// [name] => ZiHang Gao
49+
// [admin] => 1
50+
// )
51+
//
52+
// [iss] => http://example.org
53+
// [sub] => 1234567890
54+
// )
55+
print_r($decoded_token);
5856
```
5957

6058
## [Example](https://github.com./cdoco/php-jwt/tree/master/example)
6159

60+
## Algorithms and Usage
61+
62+
The JWT supports NONE, HMAC, RSASSA and ECDSA algorithms for cryptographic signing.
63+
64+
#### NONE
65+
66+
- none - unsigned token
67+
68+
```php
69+
$payload = ['data' => 'test'];
70+
71+
// IMPORTANT: set null as key parameter
72+
$token = jwt_encode($payload, null, 'none');
73+
74+
// eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.
75+
echo $token;
76+
77+
// Set key to nil and options to false otherwise this won't work
78+
$decoded_token = jwt_decode($token, null, false);
79+
80+
// Array
81+
// (
82+
// [data] => test
83+
// )
84+
print_r($decoded_token);
85+
```
86+
87+
#### HMAC (default: HS256)
88+
89+
- HS256 - HMAC using SHA-256 hash algorithm (default)
90+
- HS384 - HMAC using SHA-384 hash algorithm
91+
- HS512 - HMAC using SHA-512 hash algorithm
92+
93+
```php
94+
$hmackey = "example-hmac-key";
95+
96+
$token = jwt_encode($payload, $hmackey, 'HS256');
97+
98+
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.C8kzOqBbcaPRhRdLWdNVSvYkIPIBPu7f_8-avoG-JiU
99+
echo $token;
100+
101+
$decoded_token = jwt_decode($token, $hmackey, ['algorithm' => 'HS256']);
102+
103+
// Array
104+
// (
105+
// [data] => test
106+
// )
107+
print_r($decoded_token);
108+
```
109+
110+
#### RSA
111+
112+
- RS256 - RSA using SHA-256 hash algorithm
113+
- RS384 - RSA using SHA-384 hash algorithm
114+
- RS512 - RSA using SHA-512 hash algorithm
115+
116+
```php
117+
$privateKey = file_get_contents('key/rsa_private_key.pem');
118+
$publicKey = file_get_contents('key/rsa_public_key.pem');
119+
120+
$token = jwt_encode($payload, $privateKey, 'RS256');
121+
122+
// eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pkpKlkzQWSkme42WcOxwkLeUttiLeNORzthSJeIt140iNEtRK_f8IotoinfIKI7Y6x8pfQ4n1DHJ_5IUDe6elds8gnhLwfq5XRY48BGc8Dc_QowVQd75m5fXI6nFySW8z8CAsbwn2Efg-p7SLdfhWpNQ9AISfwa_1l-OB3BgKFw
123+
echo $token;
124+
125+
$decoded_token = jwt_decode($token, $publicKey, ['algorithm' => 'RS256']);
126+
127+
// Array
128+
// (
129+
// [data] => test
130+
// )
131+
print_r($decoded_token);
132+
```
133+
134+
#### ECDSA
135+
136+
- ES256 - ECDSA using P-256 and SHA-256
137+
- ES384 - ECDSA using P-384 and SHA-384
138+
- ES512 - ECDSA using P-521 and SHA-512
139+
140+
```php
141+
$privateKey = file_get_contents('key/ec_private_key.pem');
142+
$publicKey = file_get_contents('key/ec_public_key.pem');
143+
144+
$token = jwt_encode($payload, $privateKey, 'ES256');
145+
146+
// eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.etzxzSvJi1QS5nUtKDuLX2sScZ5W50CJL6PivKys45nc77QLxnLsF5QQApEAis8SI28rqwP9VITqPPlwJBNdH3N5n0I58z3jevGJYOfRtBnCa6omUNE03nxoEYMqRBuP
147+
echo $token;
148+
149+
$decoded_token = jwt_decode($token, $publicKey, ['algorithm' => 'ES256']);
150+
151+
// Array
152+
// (
153+
// [data] => test
154+
// )
155+
print_r($decoded_token);
156+
```
157+
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+
> The `aud` (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the `aud` claim when this claim is present, then the JWT MUST be rejected. In the general case, the `aud` value is an array of case-sensitive strings, each containing a **StringOrURI** value. In the special case when the JWT has one audience, the `aud` value MAY be a single case-sensitive string containing a **StringOrURI** value. The interpretation of audience values is generally application specific. Use of this claim is OPTIONAL.
256+
257+
```php
258+
$payload = ['data' => 'data', 'aud' => 'Young Man'];
259+
260+
$token = jwt_encode($payload, $hmackey, 'HS256');
261+
262+
try {
263+
$decoded_token = jwt_decode($token, $hmackey, ['aud' => 'Young Man', 'algorithm' => 'HS256']);
264+
} catch (Exception $e) {
265+
// Handle invalid token
266+
}
267+
```
268+
269+
### JWT ID Claim
270+
271+
> The `jti` (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The `jti` claim can be used to prevent the JWT from being replayed. The `jti` value is a **case-sensitive string**. Use of this claim is OPTIONAL.
272+
273+
```php
274+
$payload = ['data' => 'data', 'jti' => md5('id')];
275+
276+
$token = jwt_encode($payload, $hmackey, 'HS256');
277+
278+
try {
279+
$decoded_token = jwt_decode($token, $hmackey, ['jti' => md5('id'), 'algorithm' => 'HS256']);
280+
} catch (Exception $e) {
281+
// Handle invalid token
282+
}
283+
```
284+
285+
### Issued At Claim
286+
287+
> The `iat` (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a **NumericDate** value. Use of this claim is OPTIONAL.
288+
289+
```php
290+
$payload = ['data' => 'data', 'iat' => time()];
291+
292+
$token = jwt_encode($payload, $hmackey, 'HS256');
293+
294+
try {
295+
$decoded_token = jwt_decode($token, $hmackey, ['algorithm' => 'HS256']);
296+
} catch (Exception $e) {
297+
// Handle invalid token
298+
}
299+
```
300+
301+
### Subject Claim
302+
303+
> The `sub` (subject) claim identifies the principal that is the subject of the JWT. The Claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The sub value is a case-sensitive string containing a **StringOrURI** value. Use of this claim is OPTIONAL.
304+
305+
```php
306+
$payload = ['data' => 'data', 'sub' => 'Subject'];
307+
308+
$token = jwt_encode($payload, $hmackey, 'HS256');
309+
310+
try {
311+
$decoded_token = jwt_decode($token, $hmackey, ['sub' => 'Subject', 'algorithm' => 'HS256']);
312+
} catch (Exception $e) {
313+
// Handle invalid token
314+
}
315+
```
316+
62317
## Benchmarks
63318

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

66-
## Methods
321+
## Functions
67322

68323
```php
69324
//encode
70-
string jwt_encode(array $claims, string $key [, string $alg = 'HS256'])
325+
string jwt_encode(array $claims, string $key [, string $algorithm = 'HS256'])
71326

72327
//decode
73-
array jwt_decode(string $token, string $key [, string $alg = 'HS256'])
328+
array jwt_decode(string $token, string $key [, array $options = ['algorithm' => 'HS256']])
74329
```
75330

76331
## The algorithm of support
@@ -81,6 +336,13 @@ HMAC|HS256|HS384|HS512
81336
RSA|RS256|RS384|RS512
82337
ECDSA|ES256|ES384|ES512
83338

339+
## Inspired By
340+
341+
- <https://github.com./benmcollins/libjwt>
342+
- <https://github.com./firebase/php-jwt>
343+
- <https://github.com./kohkimakimoto/php-jwt>
344+
- <https://github.com./jwt/ruby-jwt>
345+
84346
## License
85347

86348
PHP License. See the [LICENSE](LICENSE) file.

example/ecdsa.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
-----END PUBLIC KEY-----
1818
EOD;
1919

20-
$claims = array(
20+
$payload = array(
2121
"data" => [
2222
"name" => "ZiHang Gao",
2323
"admin" => true
@@ -26,7 +26,7 @@
2626
"sub" => "1234567890",
2727
);
2828

29-
$token = jwt_encode($claims, $privateKey, 'ES256');
29+
$token = jwt_encode($payload, $privateKey, 'ES256');
3030

3131
echo $token . PHP_EOL;
32-
print_r(jwt_decode($token, $publicKey, 'ES256'));
32+
print_r(jwt_decode($token, $publicKey, ['algorithm' => 'ES256']));

example/hmac.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
$key = "example_key";
4-
$claims = array(
4+
$payload = array(
55
"data" => [
66
"name" => "ZiHang Gao",
77
"admin" => true
@@ -11,7 +11,7 @@
1111
);
1212

1313
// default HS256 algorithm
14-
$token = jwt_encode($claims, $key);
14+
$token = jwt_encode($payload, $key);
1515

1616
echo $token . PHP_EOL;
1717
print_r(jwt_decode($token, $key));

0 commit comments

Comments
 (0)