Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

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