Rev 637 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
597 | daniel-mar | 1 | [![Build Status](https://travis-ci.org/firebase/php-jwt.png?branch=master)](https://travis-ci.org/firebase/php-jwt) |
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 | |||
637 | daniel-mar | 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 | |||
597 | daniel-mar | 26 | Example |
27 | ------- |
||
28 | ```php |
||
618 | daniel-mar | 29 | use Firebase\JWT\JWT; |
679 | daniel-mar | 30 | use Firebase\JWT\Key; |
597 | daniel-mar | 31 | |
32 | $key = "example_key"; |
||
33 | $payload = array( |
||
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 | */ |
||
679 | daniel-mar | 46 | $jwt = JWT::encode($payload, $key, 'HS256'); |
47 | $decoded = JWT::decode($jwt, new Key($key, 'HS256')); |
||
597 | daniel-mar | 48 | |
49 | print_r($decoded); |
||
50 | |||
51 | /* |
||
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: |
||
54 | */ |
||
55 | |||
56 | $decoded_array = (array) $decoded; |
||
57 | |||
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 |
||
679 | daniel-mar | 66 | $decoded = JWT::decode($jwt, new Key($key, 'HS256')); |
597 | daniel-mar | 67 | ``` |
68 | Example with RS256 (openssl) |
||
69 | ---------------------------- |
||
70 | ```php |
||
618 | daniel-mar | 71 | use Firebase\JWT\JWT; |
679 | daniel-mar | 72 | use Firebase\JWT\Key; |
597 | daniel-mar | 73 | |
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; |
||
91 | |||
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; |
||
100 | |||
101 | $payload = array( |
||
102 | "iss" => "example.org", |
||
103 | "aud" => "example.com", |
||
104 | "iat" => 1356999524, |
||
105 | "nbf" => 1357000000 |
||
106 | ); |
||
107 | |||
108 | $jwt = JWT::encode($payload, $privateKey, 'RS256'); |
||
109 | echo "Encode:\n" . print_r($jwt, true) . "\n"; |
||
110 | |||
679 | daniel-mar | 111 | $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); |
597 | daniel-mar | 112 | |
113 | /* |
||
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: |
||
116 | */ |
||
117 | |||
118 | $decoded_array = (array) $decoded; |
||
119 | echo "Decode:\n" . print_r($decoded_array, true) . "\n"; |
||
120 | ``` |
||
121 | |||
618 | daniel-mar | 122 | Example with a passphrase |
123 | ------------------------- |
||
124 | |||
125 | ```php |
||
679 | daniel-mar | 126 | use Firebase\JWT\JWT; |
127 | use Firebase\JWT\Key; |
||
128 | |||
618 | daniel-mar | 129 | // Your passphrase |
130 | $passphrase = '[YOUR_PASSPHRASE]'; |
||
131 | |||
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'; |
||
135 | |||
136 | // Create a private key of type "resource" |
||
137 | $privateKey = openssl_pkey_get_private( |
||
138 | file_get_contents($privateKeyFile), |
||
139 | $passphrase |
||
140 | ); |
||
141 | |||
142 | $payload = array( |
||
143 | "iss" => "example.org", |
||
144 | "aud" => "example.com", |
||
145 | "iat" => 1356999524, |
||
146 | "nbf" => 1357000000 |
||
147 | ); |
||
148 | |||
149 | $jwt = JWT::encode($payload, $privateKey, 'RS256'); |
||
150 | echo "Encode:\n" . print_r($jwt, true) . "\n"; |
||
151 | |||
152 | // Get public key from the private key, or pull from from a file. |
||
153 | $publicKey = openssl_pkey_get_details($privateKey)['key']; |
||
154 | |||
679 | daniel-mar | 155 | $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); |
618 | daniel-mar | 156 | echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; |
157 | ``` |
||
158 | |||
637 | daniel-mar | 159 | Example with EdDSA (libsodium and Ed25519 signature) |
160 | ---------------------------- |
||
161 | ```php |
||
162 | use Firebase\JWT\JWT; |
||
679 | daniel-mar | 163 | use Firebase\JWT\Key; |
637 | daniel-mar | 164 | |
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. |
||
169 | |||
170 | $keyPair = sodium_crypto_sign_keypair(); |
||
171 | |||
172 | $privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair)); |
||
173 | |||
174 | $publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair)); |
||
175 | |||
176 | $payload = array( |
||
177 | "iss" => "example.org", |
||
178 | "aud" => "example.com", |
||
179 | "iat" => 1356999524, |
||
180 | "nbf" => 1357000000 |
||
181 | ); |
||
182 | |||
183 | $jwt = JWT::encode($payload, $privateKey, 'EdDSA'); |
||
184 | echo "Encode:\n" . print_r($jwt, true) . "\n"; |
||
185 | |||
679 | daniel-mar | 186 | $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA')); |
637 | daniel-mar | 187 | echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; |
188 | ```` |
||
189 | |||
597 | daniel-mar | 190 | Using JWKs |
191 | ---------- |
||
192 | |||
193 | ```php |
||
618 | daniel-mar | 194 | use Firebase\JWT\JWK; |
195 | use Firebase\JWT\JWT; |
||
196 | |||
597 | daniel-mar | 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' => []]; |
||
200 | |||
201 | // JWK::parseKeySet($jwks) returns an associative array of **kid** to private |
||
202 | // key. Pass this as the second parameter to JWT::decode. |
||
679 | daniel-mar | 203 | // NOTE: The deprecated $supportedAlgorithm must be supplied when parsing from JWK. |
597 | daniel-mar | 204 | JWT::decode($payload, JWK::parseKeySet($jwks), $supportedAlgorithm); |
205 | ``` |
||
206 | |||
207 | Changelog |
||
208 | --------- |
||
209 | |||
210 | #### 5.0.0 / 2017-06-26 |
||
211 | - Support RS384 and RS512. |
||
212 | See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)! |
||
213 | - Add an example for RS256 openssl. |
||
214 | See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)! |
||
215 | - Detect invalid Base64 encoding in signature. |
||
216 | See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)! |
||
217 | - Update `JWT::verify` to handle OpenSSL errors. |
||
218 | See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)! |
||
219 | - Add `array` type hinting to `decode` method |
||
220 | See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)! |
||
221 | - Add all JSON error types. |
||
222 | See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)! |
||
223 | - Bugfix 'kid' not in given key list. |
||
224 | See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)! |
||
225 | - Miscellaneous cleanup, documentation and test fixes. |
||
226 | See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115), |
||
227 | [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and |
||
228 | [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman), |
||
229 | [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)! |
||
230 | |||
231 | #### 4.0.0 / 2016-07-17 |
||
232 | - 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)! |
||
233 | - 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)! |
||
234 | - Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)! |
||
235 | - Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)! |
||
236 | |||
237 | #### 3.0.0 / 2015-07-22 |
||
238 | - Minimum PHP version updated from `5.2.0` to `5.3.0`. |
||
239 | - Add `\Firebase\JWT` namespace. See |
||
240 | [#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to |
||
241 | [@Dashron](https://github.com/Dashron)! |
||
242 | - Require a non-empty key to decode and verify a JWT. See |
||
243 | [#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to |
||
244 | [@sjones608](https://github.com/sjones608)! |
||
245 | - Cleaner documentation blocks in the code. See |
||
246 | [#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to |
||
247 | [@johanderuijter](https://github.com/johanderuijter)! |
||
248 | |||
249 | #### 2.2.0 / 2015-06-22 |
||
250 | - Add support for adding custom, optional JWT headers to `JWT::encode()`. See |
||
251 | [#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to |
||
252 | [@mcocaro](https://github.com/mcocaro)! |
||
253 | |||
254 | #### 2.1.0 / 2015-05-20 |
||
255 | - Add support for adding a leeway to `JWT:decode()` that accounts for clock skew |
||
256 | between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)! |
||
257 | - Add support for passing an object implementing the `ArrayAccess` interface for |
||
258 | `$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)! |
||
259 | |||
260 | #### 2.0.0 / 2015-04-01 |
||
261 | - **Note**: It is strongly recommended that you update to > v2.0.0 to address |
||
262 | known security vulnerabilities in prior versions when both symmetric and |
||
263 | asymmetric keys are used together. |
||
264 | - Update signature for `JWT::decode(...)` to require an array of supported |
||
265 | algorithms to use when verifying token signatures. |
||
266 | |||
267 | |||
268 | Tests |
||
269 | ----- |
||
270 | Run the tests using phpunit: |
||
271 | |||
272 | ```bash |
||
273 | $ pear install PHPUnit |
||
274 | $ phpunit --configuration phpunit.xml.dist |
||
275 | PHPUnit 3.7.10 by Sebastian Bergmann. |
||
276 | ..... |
||
277 | Time: 0 seconds, Memory: 2.50Mb |
||
278 | OK (5 tests, 5 assertions) |
||
279 | ``` |
||
280 | |||
281 | New Lines in private keys |
||
282 | ----- |
||
283 | |||
284 | If your private key contains `\n` characters, be sure to wrap it in double quotes `""` |
||
285 | and not single quotes `''` in order to properly interpret the escaped characters. |
||
286 | |||
287 | License |
||
288 | ------- |
||
289 | [3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause). |