Merge branch 'MDL-75604-401' of https://github.com/ssj365/moodle into MOODLE_401_STABLE
[moodle.git] / lib / php-jwt / README.md
blobfed1e9541b05bf3f0ad4717a0701d90d76bdbb39
1 ![Build Status](https://github.com/firebase/php-jwt/actions/workflows/tests.yml/badge.svg)
2 [![Latest Stable Version](https://poser.pugx.org/firebase/php-jwt/v/stable)](https://packagist.org/packages/firebase/php-jwt)
3 [![Total Downloads](https://poser.pugx.org/firebase/php-jwt/downloads)](https://packagist.org/packages/firebase/php-jwt)
4 [![License](https://poser.pugx.org/firebase/php-jwt/license)](https://packagist.org/packages/firebase/php-jwt)
6 PHP-JWT
7 =======
8 A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).
10 Installation
11 ------------
13 Use composer to manage your dependencies and download PHP-JWT:
15 ```bash
16 composer require firebase/php-jwt
17 ```
19 Optionally, install the `paragonie/sodium_compat` package from composer if your
20 php is < 7.2 or does not have libsodium installed:
22 ```bash
23 composer require paragonie/sodium_compat
24 ```
26 Example
27 -------
28 ```php
29 use Firebase\JWT\JWT;
30 use Firebase\JWT\Key;
32 $key = 'example_key';
33 $payload = [
34     'iss' => 'http://example.org',
35     'aud' => 'http://example.com',
36     'iat' => 1356999524,
37     'nbf' => 1357000000
40 /**
41  * IMPORTANT:
42  * You must specify supported algorithms for your application. See
43  * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
44  * for a list of spec-compliant algorithms.
45  */
46 $jwt = JWT::encode($payload, $key, 'HS256');
47 $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
49 print_r($decoded);
52  NOTE: This will now be an object instead of an associative array. To get
53  an associative array, you will need to cast it as such:
56 $decoded_array = (array) $decoded;
58 /**
59  * You can add a leeway to account for when there is a clock skew times between
60  * the signing and verifying servers. It is recommended that this leeway should
61  * not be bigger than a few minutes.
62  *
63  * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
64  */
65 JWT::$leeway = 60; // $leeway in seconds
66 $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
67 ```
68 Example with RS256 (openssl)
69 ----------------------------
70 ```php
71 use Firebase\JWT\JWT;
72 use Firebase\JWT\Key;
74 $privateKey = <<<EOD
75 -----BEGIN RSA PRIVATE KEY-----
76 MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
77 vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
78 5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
79 AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
80 bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
81 Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
82 cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
83 5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
84 ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
85 k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
86 qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
87 eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
88 B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
89 -----END RSA PRIVATE KEY-----
90 EOD;
92 $publicKey = <<<EOD
93 -----BEGIN PUBLIC KEY-----
94 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H
95 4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t
96 0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4
97 ehde/zUxo6UvS7UrBQIDAQAB
98 -----END PUBLIC KEY-----
99 EOD;
101 $payload = [
102     'iss' => 'example.org',
103     'aud' => 'example.com',
104     'iat' => 1356999524,
105     'nbf' => 1357000000
108 $jwt = JWT::encode($payload, $privateKey, 'RS256');
109 echo "Encode:\n" . print_r($jwt, true) . "\n";
111 $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
114  NOTE: This will now be an object instead of an associative array. To get
115  an associative array, you will need to cast it as such:
118 $decoded_array = (array) $decoded;
119 echo "Decode:\n" . print_r($decoded_array, true) . "\n";
122 Example with a passphrase
123 -------------------------
125 ```php
126 use Firebase\JWT\JWT;
127 use Firebase\JWT\Key;
129 // Your passphrase
130 $passphrase = '[YOUR_PASSPHRASE]';
132 // Your private key file with passphrase
133 // Can be generated with "ssh-keygen -t rsa -m pem"
134 $privateKeyFile = '/path/to/key-with-passphrase.pem';
136 // Create a private key of type "resource"
137 $privateKey = openssl_pkey_get_private(
138     file_get_contents($privateKeyFile),
139     $passphrase
142 $payload = [
143     'iss' => 'example.org',
144     'aud' => 'example.com',
145     'iat' => 1356999524,
146     'nbf' => 1357000000
149 $jwt = JWT::encode($payload, $privateKey, 'RS256');
150 echo "Encode:\n" . print_r($jwt, true) . "\n";
152 // Get public key from the private key, or pull from from a file.
153 $publicKey = openssl_pkey_get_details($privateKey)['key'];
155 $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
156 echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
159 Example with EdDSA (libsodium and Ed25519 signature)
160 ----------------------------
161 ```php
162 use Firebase\JWT\JWT;
163 use Firebase\JWT\Key;
165 // Public and private keys are expected to be Base64 encoded. The last
166 // non-empty line is used so that keys can be generated with
167 // sodium_crypto_sign_keypair(). The secret keys generated by other tools may
168 // need to be adjusted to match the input expected by libsodium.
170 $keyPair = sodium_crypto_sign_keypair();
172 $privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
174 $publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
176 $payload = [
177     'iss' => 'example.org',
178     'aud' => 'example.com',
179     'iat' => 1356999524,
180     'nbf' => 1357000000
183 $jwt = JWT::encode($payload, $privateKey, 'EdDSA');
184 echo "Encode:\n" . print_r($jwt, true) . "\n";
186 $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
187 echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
188 ````
190 Using JWKs
191 ----------
193 ```php
194 use Firebase\JWT\JWK;
195 use Firebase\JWT\JWT;
197 // Set of keys. The "keys" key is required. For example, the JSON response to
198 // this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
199 $jwks = ['keys' => []];
201 // JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
202 // objects. Pass this as the second parameter to JWT::decode.
203 JWT::decode($payload, JWK::parseKeySet($jwks));
206 Using Cached Key Sets
207 ---------------------
209 The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
210 This has the following advantages:
212 1. The results are cached for performance.
213 2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
214 3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
216 ```php
217 use Firebase\JWT\CachedKeySet;
218 use Firebase\JWT\JWT;
220 // The URI for the JWKS you wish to cache the results from
221 $jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
223 // Create an HTTP client (can be any PSR-7 compatible HTTP client)
224 $httpClient = new GuzzleHttp\Client();
226 // Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
227 $httpFactory = new GuzzleHttp\Psr\HttpFactory();
229 // Create a cache item pool (can be any PSR-6 compatible cache item pool)
230 $cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
232 $keySet = new CachedKeySet(
233     $jwksUri,
234     $httpClient,
235     $httpFactory,
236     $cacheItemPool,
237     null, // $expiresAfter int seconds to set the JWKS to expire
238     true  // $rateLimit    true to enable rate limit of 10 RPS on lookup of invalid keys
241 $jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
242 $decoded = JWT::decode($jwt, $keySet);
245 Miscellaneous
246 -------------
248 #### Casting to array
250 The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
251 instead, you can do the following:
253 ```php
254 // return type is stdClass
255 $decoded = JWT::decode($payload, $keys);
257 // cast to array
258 $decoded = json_decode(json_encode($decoded), true);
261 Changelog
262 ---------
264 #### 6.3.0 / 2022-07-15
266  - Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
267  - Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
269 #### 6.2.0 / 2022-05-14
271  - Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
272  - Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)). 
274 #### 6.1.0 / 2022-03-23
276  - Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
277  - Add parameter typing and return types where possible
279 #### 6.0.0 / 2022-01-24
281  - **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
282  - New Key object to prevent key/algorithm type confusion (#365)
283  - Add JWK support (#273)
284  - Add ES256 support (#256)
285  - Add ES384 support (#324)
286  - Add Ed25519 support (#343)
288 #### 5.0.0 / 2017-06-26
289 - Support RS384 and RS512.
290   See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
291 - Add an example for RS256 openssl.
292   See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
293 - Detect invalid Base64 encoding in signature.
294   See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
295 - Update `JWT::verify` to handle OpenSSL errors.
296   See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
297 - Add `array` type hinting to `decode` method
298   See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
299 - Add all JSON error types.
300   See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
301 - Bugfix 'kid' not in given key list.
302   See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
303 - Miscellaneous cleanup, documentation and test fixes.
304   See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
305   [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
306   [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
307   [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
309 #### 4.0.0 / 2016-07-17
310 - Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
311 - Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
312 - Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
313 - Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
315 #### 3.0.0 / 2015-07-22
316 - Minimum PHP version updated from `5.2.0` to `5.3.0`.
317 - Add `\Firebase\JWT` namespace. See
318 [#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
319 [@Dashron](https://github.com/Dashron)!
320 - Require a non-empty key to decode and verify a JWT. See
321 [#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
322 [@sjones608](https://github.com/sjones608)!
323 - Cleaner documentation blocks in the code. See
324 [#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
325 [@johanderuijter](https://github.com/johanderuijter)!
327 #### 2.2.0 / 2015-06-22
328 - Add support for adding custom, optional JWT headers to `JWT::encode()`. See
329 [#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
330 [@mcocaro](https://github.com/mcocaro)!
332 #### 2.1.0 / 2015-05-20
333 - Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
334 between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
335 - Add support for passing an object implementing the `ArrayAccess` interface for
336 `$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
338 #### 2.0.0 / 2015-04-01
339 - **Note**: It is strongly recommended that you update to > v2.0.0 to address
340   known security vulnerabilities in prior versions when both symmetric and
341   asymmetric keys are used together.
342 - Update signature for `JWT::decode(...)` to require an array of supported
343   algorithms to use when verifying token signatures.
346 Tests
347 -----
348 Run the tests using phpunit:
350 ```bash
351 $ pear install PHPUnit
352 $ phpunit --configuration phpunit.xml.dist
353 PHPUnit 3.7.10 by Sebastian Bergmann.
354 .....
355 Time: 0 seconds, Memory: 2.50Mb
356 OK (5 tests, 5 assertions)
359 New Lines in private keys
360 -----
362 If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
363 and not single quotes `''` in order to properly interpret the escaped characters.
365 License
366 -------
367 [3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).