Proyectos de Subversion Moodle

Rev

| 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
20
php is < 7.2 or does not have libsodium installed:
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
51
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass());
52
print_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
 */
68
JWT::$leeway = 60; // $leeway in seconds
69
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
70
```
71
Example encode/decode headers
72
-------
73
Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
74
this library. This is because without verifying the JWT, the header values could have been tampered with.
75
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
76
attacker.  If this is something you still want to do in your application for whatever reason, it's possible to
77
decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
78
header part:
79
```php
80
use 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.
100
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
101
$decoded = json_decode(base64_decode($headersB64), true);
102
 
103
print_r($decoded);
104
```
105
Example with RS256 (openssl)
106
----------------------------
107
```php
108
use Firebase\JWT\JWT;
109
use Firebase\JWT\Key;
110
 
111
$privateKey = <<<EOD
112
-----BEGIN RSA PRIVATE KEY-----
113
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
114
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
115
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
116
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
117
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
118
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
119
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
120
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
121
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
122
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
123
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
124
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
125
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
126
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
127
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
128
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
129
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
130
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
131
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
132
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
133
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
134
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
135
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
136
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
137
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
138
-----END RSA PRIVATE KEY-----
139
EOD;
140
 
141
$publicKey = <<<EOD
142
-----BEGIN PUBLIC KEY-----
143
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
144
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
145
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
146
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
147
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
148
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
149
wQIDAQAB
150
-----END PUBLIC KEY-----
151
EOD;
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');
161
echo "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;
171
echo "Decode:\n" . print_r($decoded_array, true) . "\n";
172
```
173
 
174
Example with a passphrase
175
-------------------------
176
 
177
```php
178
use Firebase\JWT\JWT;
179
use 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');
202
echo "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'));
208
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
209
```
210
 
211
Example with EdDSA (libsodium and Ed25519 signature)
212
----------------------------
213
```php
214
use Firebase\JWT\JWT;
215
use 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');
236
echo "Encode:\n" . print_r($jwt, true) . "\n";
237
 
238
$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
239
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
240
````
241
 
242
Example with multiple keys
243
--------------------------
244
```php
245
use Firebase\JWT\JWT;
246
use 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');
265
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
266
echo "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
 
276
echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
277
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
278
```
279
 
280
Using JWKs
281
----------
282
 
283
```php
284
use Firebase\JWT\JWK;
285
use 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.
293
JWT::decode($payload, JWK::parseKeySet($jwks));
294
```
295
 
296
Using Cached Key Sets
297
---------------------
298
 
299
The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
300
This has the following advantages:
301
 
302
1. The results are cached for performance.
303
2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
304
3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
305
 
306
```php
307
use Firebase\JWT\CachedKeySet;
308
use 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
 
335
Miscellaneous
336
-------------
337
 
338
#### Exception Handling
339
 
340
When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
341
 
342
```php
343
use Firebase\JWT\JWT;
344
use Firebase\JWT\SignatureInvalidException;
345
use Firebase\JWT\BeforeValidException;
346
use Firebase\JWT\ExpiredException;
347
use DomainException;
348
use InvalidArgumentException;
349
use UnexpectedValueException;
350
 
351
try {
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
 
375
All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
376
like this:
377
 
378
```php
379
use Firebase\JWT\JWT;
380
use UnexpectedValueException;
381
try {
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
 
392
The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
393
instead, 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
 
403
Tests
404
-----
405
Run the tests using phpunit:
406
 
407
```bash
408
$ pear install PHPUnit
409
$ phpunit --configuration phpunit.xml.dist
410
PHPUnit 3.7.10 by Sebastian Bergmann.
411
.....
412
Time: 0 seconds, Memory: 2.50Mb
413
OK (5 tests, 5 assertions)
414
```
415
 
416
New Lines in private keys
417
-----
418
 
419
If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
420
and not single quotes `''` in order to properly interpret the escaped characters.
421
 
422
License
423
-------
424
[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).