source: vendor/firebase/php-jwt/README.md

Last change on this file was e3d4e0a, checked in by Vlado 222039 <vlado.popovski@…>, 7 days ago

Upload project files

  • Property mode set to 100644
File size: 13.2 KB
Line 
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)
5
6PHP-JWT
7=======
8A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).
9
10Installation
11------------
12
13Use composer to manage your dependencies and download PHP-JWT:
14
15```bash
16composer require firebase/php-jwt
17```
18
19Optionally, install the `paragonie/sodium_compat` package from composer if your
20php env does not have libsodium installed:
21
22```bash
23composer require paragonie/sodium_compat
24```
25
26Example
27-------
28```php
29use Firebase\JWT\JWT;
30use Firebase\JWT\Key;
31
32$key = 'example_key';
33$payload = [
34 'iss' => 'http://example.org',
35 'aud' => 'http://example.com',
36 'iat' => 1356999524,
37 'nbf' => 1357000000
38];
39
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'));
48print_r($decoded);
49
50// Pass a stdClass in as the third parameter to get the decoded header values
51$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass());
52print_r($headers);
53
54/*
55 NOTE: This will now be an object instead of an associative array. To get
56 an associative array, you will need to cast it as such:
57*/
58
59$decoded_array = (array) $decoded;
60
61/**
62 * You can add a leeway to account for when there is a clock skew times between
63 * the signing and verifying servers. It is recommended that this leeway should
64 * not be bigger than a few minutes.
65 *
66 * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
67 */
68JWT::$leeway = 60; // $leeway in seconds
69$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
70```
71Example encode/decode headers
72-------
73Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
74this library. This is because without verifying the JWT, the header values could have been tampered with.
75Any value pulled from an unverified header should be treated as if it could be any string sent in from an
76attacker. If this is something you still want to do in your application for whatever reason, it's possible to
77decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
78header part:
79```php
80use Firebase\JWT\JWT;
81
82$key = 'example_key';
83$payload = [
84 'iss' => 'http://example.org',
85 'aud' => 'http://example.com',
86 'iat' => 1356999524,
87 'nbf' => 1357000000
88];
89
90$headers = [
91 'x-forwarded-for' => 'www.google.com'
92];
93
94// Encode headers in the JWT string
95$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
96
97// Decode headers from the JWT string WITHOUT validation
98// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
99// These headers could be any value sent by an attacker.
100list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
101$decoded = json_decode(base64_decode($headersB64), true);
102
103print_r($decoded);
104```
105Example with RS256 (openssl)
106----------------------------
107```php
108use Firebase\JWT\JWT;
109use Firebase\JWT\Key;
110
111$privateKey = <<<EOD
112-----BEGIN RSA PRIVATE KEY-----
113MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
114M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
115JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
11678pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
117HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
118WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
1196yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
120VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
121oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
122c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
123h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
124bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
12539y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
1263T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
127vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
1286Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
129OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
130nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
131xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
1328AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
133hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
134YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
135DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
136RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
1372MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
138-----END RSA PRIVATE KEY-----
139EOD;
140
141$publicKey = <<<EOD
142-----BEGIN PUBLIC KEY-----
143MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
144fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
145hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
146u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
147opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
148TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
149wQIDAQAB
150-----END PUBLIC KEY-----
151EOD;
152
153$payload = [
154 'iss' => 'example.org',
155 'aud' => 'example.com',
156 'iat' => 1356999524,
157 'nbf' => 1357000000
158];
159
160$jwt = JWT::encode($payload, $privateKey, 'RS256');
161echo "Encode:\n" . print_r($jwt, true) . "\n";
162
163$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
164
165/*
166 NOTE: This will now be an object instead of an associative array. To get
167 an associative array, you will need to cast it as such:
168*/
169
170$decoded_array = (array) $decoded;
171echo "Decode:\n" . print_r($decoded_array, true) . "\n";
172```
173
174Example with a passphrase
175-------------------------
176
177```php
178use Firebase\JWT\JWT;
179use Firebase\JWT\Key;
180
181// Your passphrase
182$passphrase = '[YOUR_PASSPHRASE]';
183
184// Your private key file with passphrase
185// Can be generated with "ssh-keygen -t rsa -m pem"
186$privateKeyFile = '/path/to/key-with-passphrase.pem';
187
188// Create a private key of type "resource"
189$privateKey = openssl_pkey_get_private(
190 file_get_contents($privateKeyFile),
191 $passphrase
192);
193
194$payload = [
195 'iss' => 'example.org',
196 'aud' => 'example.com',
197 'iat' => 1356999524,
198 'nbf' => 1357000000
199];
200
201$jwt = JWT::encode($payload, $privateKey, 'RS256');
202echo "Encode:\n" . print_r($jwt, true) . "\n";
203
204// Get public key from the private key, or pull from from a file.
205$publicKey = openssl_pkey_get_details($privateKey)['key'];
206
207$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
208echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
209```
210
211Example with EdDSA (libsodium and Ed25519 signature)
212----------------------------
213```php
214use Firebase\JWT\JWT;
215use Firebase\JWT\Key;
216
217// Public and private keys are expected to be Base64 encoded. The last
218// non-empty line is used so that keys can be generated with
219// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
220// need to be adjusted to match the input expected by libsodium.
221
222$keyPair = sodium_crypto_sign_keypair();
223
224$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
225
226$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
227
228$payload = [
229 'iss' => 'example.org',
230 'aud' => 'example.com',
231 'iat' => 1356999524,
232 'nbf' => 1357000000
233];
234
235$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
236echo "Encode:\n" . print_r($jwt, true) . "\n";
237
238$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
239echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
240````
241
242Example with multiple keys
243--------------------------
244```php
245use Firebase\JWT\JWT;
246use Firebase\JWT\Key;
247
248// Example RSA keys from previous example
249// $privateKey1 = '...';
250// $publicKey1 = '...';
251
252// Example EdDSA keys from previous example
253// $privateKey2 = '...';
254// $publicKey2 = '...';
255
256$payload = [
257 'iss' => 'example.org',
258 'aud' => 'example.com',
259 'iat' => 1356999524,
260 'nbf' => 1357000000
261];
262
263$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
264$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
265echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
266echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
267
268$keys = [
269 'kid1' => new Key($publicKey1, 'RS256'),
270 'kid2' => new Key($publicKey2, 'EdDSA'),
271];
272
273$decoded1 = JWT::decode($jwt1, $keys);
274$decoded2 = JWT::decode($jwt2, $keys);
275
276echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
277echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
278```
279
280Using JWKs
281----------
282
283```php
284use Firebase\JWT\JWK;
285use Firebase\JWT\JWT;
286
287// Set of keys. The "keys" key is required. For example, the JSON response to
288// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
289$jwks = ['keys' => []];
290
291// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
292// objects. Pass this as the second parameter to JWT::decode.
293JWT::decode($payload, JWK::parseKeySet($jwks));
294```
295
296Using Cached Key Sets
297---------------------
298
299The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
300This has the following advantages:
301
3021. The results are cached for performance.
3032. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
3043. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
305
306```php
307use Firebase\JWT\CachedKeySet;
308use Firebase\JWT\JWT;
309
310// The URI for the JWKS you wish to cache the results from
311$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
312
313// Create an HTTP client (can be any PSR-7 compatible HTTP client)
314$httpClient = new GuzzleHttp\Client();
315
316// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
317$httpFactory = new GuzzleHttp\Psr\HttpFactory();
318
319// Create a cache item pool (can be any PSR-6 compatible cache item pool)
320$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
321
322$keySet = new CachedKeySet(
323 $jwksUri,
324 $httpClient,
325 $httpFactory,
326 $cacheItemPool,
327 null, // $expiresAfter int seconds to set the JWKS to expire
328 true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
329);
330
331$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
332$decoded = JWT::decode($jwt, $keySet);
333```
334
335Miscellaneous
336-------------
337
338#### Exception Handling
339
340When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
341
342```php
343use Firebase\JWT\JWT;
344use Firebase\JWT\SignatureInvalidException;
345use Firebase\JWT\BeforeValidException;
346use Firebase\JWT\ExpiredException;
347use DomainException;
348use InvalidArgumentException;
349use UnexpectedValueException;
350
351try {
352 $decoded = JWT::decode($payload, $keys);
353} catch (InvalidArgumentException $e) {
354 // provided key/key-array is empty or malformed.
355} catch (DomainException $e) {
356 // provided algorithm is unsupported OR
357 // provided key is invalid OR
358 // unknown error thrown in openSSL or libsodium OR
359 // libsodium is required but not available.
360} catch (SignatureInvalidException $e) {
361 // provided JWT signature verification failed.
362} catch (BeforeValidException $e) {
363 // provided JWT is trying to be used before "nbf" claim OR
364 // provided JWT is trying to be used before "iat" claim.
365} catch (ExpiredException $e) {
366 // provided JWT is trying to be used after "exp" claim.
367} catch (UnexpectedValueException $e) {
368 // provided JWT is malformed OR
369 // provided JWT is missing an algorithm / using an unsupported algorithm OR
370 // provided JWT algorithm does not match provided key OR
371 // provided key ID in key/key-array is empty or invalid.
372}
373```
374
375All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
376like this:
377
378```php
379use Firebase\JWT\JWT;
380use UnexpectedValueException;
381try {
382 $decoded = JWT::decode($payload, $keys);
383} catch (LogicException $e) {
384 // errors having to do with environmental setup or malformed JWT Keys
385} catch (UnexpectedValueException $e) {
386 // errors having to do with JWT signature and claims
387}
388```
389
390#### Casting to array
391
392The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
393instead, you can do the following:
394
395```php
396// return type is stdClass
397$decoded = JWT::decode($payload, $keys);
398
399// cast to array
400$decoded = json_decode(json_encode($decoded), true);
401```
402
403Tests
404-----
405Run the tests using phpunit:
406
407```bash
408$ pear install PHPUnit
409$ phpunit --configuration phpunit.xml.dist
410PHPUnit 3.7.10 by Sebastian Bergmann.
411.....
412Time: 0 seconds, Memory: 2.50Mb
413OK (5 tests, 5 assertions)
414```
415
416New Lines in private keys
417-----
418
419If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
420and not single quotes `''` in order to properly interpret the escaped characters.
421
422License
423-------
424[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
Note: See TracBrowser for help on using the repository browser.