├── .gitignore
├── JWT_AUTH.php
├── License
├── README.md
├── assets
├── css
│ └── settings.css
└── img
│ └── jwticon.png
├── banner-1544x500.png
├── banner-772x250.png
├── icon-128x128.png
├── icon-256x256.png
├── lib
├── JWT_AUTH_Admin.php
├── JWT_AUTH_Options.php
├── JWT_AUTH_Settings_Section.php
├── JWT_AUTH_UserProcessor.php
├── JWT_AUTH_UsersRepo.php
└── php-jwt
│ ├── Authentication
│ └── JWT.php
│ ├── Exceptions
│ ├── BeforeValidException.php
│ ├── ExpiredException.php
│ └── SignatureInvalidException.php
│ ├── LICENSE
│ ├── README.md
│ ├── composer.json
│ ├── package.xml
│ ├── phpunit.xml.dist
│ ├── run-tests.sh
│ └── tests
│ ├── JWTTest.php
│ ├── autoload.php.dist
│ └── bootstrap.php
├── readme.txt
└── templates
└── settings.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/JWT_AUTH.php:
--------------------------------------------------------------------------------
1 | Settings';
86 | array_unshift($links, $settings_link);
87 |
88 | return $links;
89 | }
90 |
91 | public static function getPluginDirUrl()
92 | {
93 | return plugin_dir_url( __FILE__ );
94 | }
95 |
96 | }
97 |
98 | JWT_AUTH::Init();
99 |
--------------------------------------------------------------------------------
/License:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Auth0
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED - This library is no longer maintained/supported.
2 |
3 | This library was built as an example for a session in a PHP conference, and is no longer supported.
4 |
5 | 
6 |
7 | #Wordpress JWT Authentication
8 |
9 | Authenticate your APIs with JWT easily.
10 |
11 | ##Configuration
12 | - **Aud**: represents the client id which the JWT was sent.
13 | - **Secret**: used to verify the JWT signature
14 | - **Base64 Secret Encoded**: it must be active if the secret is base64 encoded and needs to be decoded before checkig the signature.
15 | - **User Property**: is the property which much match with the JWT attribute to determine the user.
16 | - **JWT Attribute**: should match the User Property to determine the user.
17 |
18 | ##How it works
19 |
20 | This plugin will check the headers of the requests and if there is an `Authorization` header will try to log in a user that matches. So it is as easy to check for the current user to authenticate users in your own API.
21 |
22 | Also, it provides support for the following plugins:
23 | - http://wp-api.org/
24 | - http://docs.woothemes.com/document/woocommerce-rest-api/
25 |
26 | And any other that extends `Wp Rest Api` like http://tweichart.github.io/JSON-API-for-BuddyPress/ for BuddyPress.
27 |
28 |
29 | ##Overriding the User Repository logic
30 | The user repository is the responsible of retriving the user based on the JWT. By default, it looks in the user database to match the *User Property* and the *JWT Attribute*.
31 |
32 | If you need to override the way the user matching is made (ie: you need to look to another table in the database) you can create your own User Repostory and match the user as you need.
33 |
34 | To accomplish this, you need to add a filter:
35 |
36 | ```
37 | add_filter( 'wp_jwt_auth_get_user', array( __CLASS__, 'get_user' ),10);
38 | ```
39 |
40 | To see an example, check the [UsersRepo](https://github.com/auth0/wp-jwt-auth/blob/master/lib/JWT_AUTH_UsersRepo.php).
41 |
42 | > When the plugin is using a User Repository the *User Property* and *JWT Property* settings are ignored.
43 |
--------------------------------------------------------------------------------
/assets/css/settings.css:
--------------------------------------------------------------------------------
1 | input[type=text] {
2 | width: 70%;
3 | }
4 |
5 | textarea {
6 | width: 70%;
7 | height: 100px;
8 | }
9 |
10 | span.description {
11 | width: 70%;
12 | display: inline-block;
13 | }
--------------------------------------------------------------------------------
/assets/img/jwticon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auth0/wp-jwt-auth/e9dd7274e71eed35df20c3474942809f9e61352f/assets/img/jwticon.png
--------------------------------------------------------------------------------
/banner-1544x500.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auth0/wp-jwt-auth/e9dd7274e71eed35df20c3474942809f9e61352f/banner-1544x500.png
--------------------------------------------------------------------------------
/banner-772x250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auth0/wp-jwt-auth/e9dd7274e71eed35df20c3474942809f9e61352f/banner-772x250.png
--------------------------------------------------------------------------------
/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auth0/wp-jwt-auth/e9dd7274e71eed35df20c3474942809f9e61352f/icon-128x128.png
--------------------------------------------------------------------------------
/icon-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auth0/wp-jwt-auth/e9dd7274e71eed35df20c3474942809f9e61352f/icon-256x256.png
--------------------------------------------------------------------------------
/lib/JWT_AUTH_Admin.php:
--------------------------------------------------------------------------------
1 | $setting['id'])
37 | );
38 | }
39 | }
40 |
41 | public static function render_settings_description(){
42 |
43 | }
44 |
45 | public static function init_admin(){
46 |
47 | /* ------------------------- BASIC ------------------------- */
48 |
49 | self::init_option_section('Settings', array(
50 |
51 | array('id' => 'jwt_auth_aud', 'name' => 'Aud', 'function' => 'render_aud'),
52 | array('id' => 'jwt_auth_secret', 'name' => 'Secret', 'function' => 'render_secret'),
53 | array('id' => 'jwt_auth_secret_base64_encoded', 'name' => 'Base64 Secret encoded', 'function' => 'render_secret_base64_encoded'),
54 | array('id' => 'jwt_auth_user_property', 'name' => 'User Property', 'function' => 'render_user_property'),
55 | array('id' => 'jwt_auth_jwt_attribute', 'name' => 'JWT Attribute', 'function' => 'render_jwt_attribute'),
56 |
57 | ));
58 |
59 | register_setting(JWT_AUTH_Options::OPTIONS_NAME, JWT_AUTH_Options::OPTIONS_NAME, array(__CLASS__, 'input_validator'));
60 | }
61 |
62 |
63 | public static function render_aud(){
64 | $v = JWT_AUTH_Options::get( 'aud' );
65 | echo '';
66 | echo '
' . __('JWT Audience (aud) represents the client id to which it is intended.', JWT_AUTH_LANG) . '';
67 | }
68 | public static function render_secret(){
69 | $v = JWT_AUTH_Options::get( 'secret' );
70 | echo '';
71 | echo '
' . __('Secret value to verify the JWT signature.', JWT_AUTH_LANG) . '';
72 | }
73 | public static function render_secret_base64_encoded(){
74 | $v = JWT_AUTH_Options::get( 'secret_base64_encoded' );
75 | echo '';
76 | echo '';
77 | echo ' ';
78 | echo '';
79 | echo '';
80 | }
81 | public static function render_user_property(){
82 | $v = JWT_AUTH_Options::get( 'user_property' );
83 | echo '';
84 | echo '
' . __('WP User property which the plugin should look to find the related user.', JWT_AUTH_LANG) . '';
85 | }
86 | public static function render_jwt_attribute(){
87 | $v = JWT_AUTH_Options::get( 'jwt_attribute' );
88 | echo '';
89 | echo '
' . __('JWT Attribute the plugin should use to match the users.', JWT_AUTH_LANG) . '';
90 | }
91 |
92 | public static function render_settings_page(){
93 | include JWT_AUTH_PLUGIN_DIR . 'templates/settings.php';
94 | }
95 |
96 | protected static function add_validation_error($error)
97 | {
98 | add_settings_error(
99 | JWT_AUTH_Options::OPTIONS_NAME,
100 | JWT_AUTH_Options::OPTIONS_NAME,
101 | $error,
102 | 'error'
103 | );
104 | }
105 |
106 | public static function input_validator( $input ){
107 |
108 | $input['secret_base64_encoded'] = ($input['secret_base64_encoded'] == 1);
109 |
110 | return $input;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/lib/JWT_AUTH_Options.php:
--------------------------------------------------------------------------------
1 | 1,
37 | 'aud' => '',
38 | 'secret' => '',
39 | 'user_property' => 'id',
40 | 'jwt_attribute' => 'sub',
41 | 'secret_base64_encoded' => false,
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/lib/JWT_AUTH_Settings_Section.php:
--------------------------------------------------------------------------------
1 | getMessage();
75 | return null;
76 | }
77 |
78 | $objuser = self::findUser($token, $authorization);
79 |
80 | if (!$objuser) {
81 | $wp_json_basic_auth_error = 'Invalid user';
82 | return null;
83 | }
84 |
85 | if ($returnUserObj) {
86 | $user = $objuser;
87 | }
88 | else {
89 | $user = $objuser->ID;
90 | }
91 | }
92 |
93 | $wp_json_basic_auth_error = true;
94 |
95 | return $user;
96 | }
97 |
98 | protected static function decodeJWT($encUser)
99 | {
100 | require_once JWT_AUTH_PLUGIN_DIR . 'lib/php-jwt/Exceptions/BeforeValidException.php';
101 | require_once JWT_AUTH_PLUGIN_DIR . 'lib/php-jwt/Exceptions/ExpiredException.php';
102 | require_once JWT_AUTH_PLUGIN_DIR . 'lib/php-jwt/Exceptions/SignatureInvalidException.php';
103 | require_once JWT_AUTH_PLUGIN_DIR . 'lib/php-jwt/Authentication/JWT.php';
104 |
105 | $aud = JWT_AUTH_Options::get( 'aud' );
106 | $secret = JWT_AUTH_Options::get( 'secret' );
107 | $secret_base64_encoded = JWT_AUTH_Options::get( 'secret_base64_encoded' );
108 |
109 | if ($secret_base64_encoded) {
110 | $secret = base64_decode(strtr($secret, '-_', '+/'));
111 | }
112 |
113 | try {
114 | // Decode the user
115 | $decodedToken = \JWT::decode($encUser, $secret, ['HS256']);
116 |
117 | // validate that this JWT was made for us
118 | if ($decodedToken->aud != $aud) {
119 | throw new Exception("This token is not intended for us.");
120 | }
121 | } catch(\UnexpectedValueException $e) {
122 | throw new Exception($e->getMessage());
123 | }
124 |
125 | return $decodedToken;
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/lib/JWT_AUTH_UsersRepo.php:
--------------------------------------------------------------------------------
1 | $jwt_attribute;
20 |
21 | $sql = 'SELECT u.*
22 | FROM ' . $wpdb->users . '
23 | WHERE '.$user_property.' = %s';
24 |
25 | $userRow = $wpdb->get_row($wpdb->prepare($sql, $id));
26 |
27 | if (is_null($userRow)) {
28 | return null;
29 | }elseif($userRow instanceof WP_Error ) {
30 | self::insertAuth0Error('findAuth0User',$userRow);
31 | return null;
32 | }
33 | $user = new WP_User();
34 | $user->init($userRow);
35 | return $user;
36 |
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/lib/php-jwt/Authentication/JWT.php:
--------------------------------------------------------------------------------
1 |
12 | * @author Anant Narayanan
13 | * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
14 | * @link https://github.com/firebase/php-jwt
15 | */
16 | class JWT
17 | {
18 | public static $supported_algs = array(
19 | 'HS256' => array('hash_hmac', 'SHA256'),
20 | 'HS512' => array('hash_hmac', 'SHA512'),
21 | 'HS384' => array('hash_hmac', 'SHA384'),
22 | 'RS256' => array('openssl', 'SHA256'),
23 | );
24 |
25 | /**
26 | * Decodes a JWT string into a PHP object.
27 | *
28 | * @param string $jwt The JWT
29 | * @param string|Array|null $key The secret key, or map of keys
30 | * @param Array $allowed_algs List of supported verification algorithms
31 | *
32 | * @return object The JWT's payload as a PHP object
33 | *
34 | * @throws DomainException Algorithm was not provided
35 | * @throws UnexpectedValueException Provided JWT was invalid
36 | * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
37 | * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
38 | * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
39 | * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
40 | *
41 | * @uses jsonDecode
42 | * @uses urlsafeB64Decode
43 | */
44 | public static function decode($jwt, $key = null, $allowed_algs = array())
45 | {
46 | $tks = explode('.', $jwt);
47 | if (count($tks) != 3) {
48 | throw new UnexpectedValueException('Wrong number of segments');
49 | }
50 | list($headb64, $bodyb64, $cryptob64) = $tks;
51 | if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64)))) {
52 | throw new UnexpectedValueException('Invalid header encoding');
53 | }
54 | if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64))) {
55 | throw new UnexpectedValueException('Invalid claims encoding');
56 | }
57 | $sig = JWT::urlsafeB64Decode($cryptob64);
58 | if (isset($key)) {
59 | if (empty($header->alg)) {
60 | throw new DomainException('Empty algorithm');
61 | }
62 | if (empty(self::$supported_algs[$header->alg])) {
63 | throw new DomainException('Algorithm not supported');
64 | }
65 | if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
66 | throw new DomainException('Algorithm not allowed');
67 | }
68 | if (is_array($key)) {
69 | if (isset($header->kid)) {
70 | $key = $key[$header->kid];
71 | } else {
72 | throw new DomainException('"kid" empty, unable to lookup correct key');
73 | }
74 | }
75 |
76 | // Check the signature
77 | if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
78 | throw new SignatureInvalidException('Signature verification failed');
79 | }
80 |
81 | // Check if the nbf if it is defined. This is the time that the
82 | // token can actually be used. If it's not yet that time, abort.
83 | if (isset($payload->nbf) && $payload->nbf > time()) {
84 | throw new BeforeValidException(
85 | 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
86 | );
87 | }
88 |
89 | // Check that this token has been created before 'now'. This prevents
90 | // using tokens that have been created for later use (and haven't
91 | // correctly used the nbf claim).
92 | if (isset($payload->iat) && $payload->iat > time()) {
93 | throw new BeforeValidException(
94 | 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
95 | );
96 | }
97 |
98 | // Check if this token has expired.
99 | if (isset($payload->exp) && time() >= $payload->exp) {
100 | throw new ExpiredException('Expired token');
101 | }
102 | }
103 |
104 | return $payload;
105 | }
106 |
107 | /**
108 | * Converts and signs a PHP object or array into a JWT string.
109 | *
110 | * @param object|array $payload PHP object or array
111 | * @param string $key The secret key
112 | * @param string $alg The signing algorithm. Supported
113 | * algorithms are 'HS256', 'HS384' and 'HS512'
114 | *
115 | * @return string A signed JWT
116 | * @uses jsonEncode
117 | * @uses urlsafeB64Encode
118 | */
119 | public static function encode($payload, $key, $alg = 'HS256', $keyId = null)
120 | {
121 | $header = array('typ' => 'JWT', 'alg' => $alg);
122 | if ($keyId !== null) {
123 | $header['kid'] = $keyId;
124 | }
125 | $segments = array();
126 | $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header));
127 | $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload));
128 | $signing_input = implode('.', $segments);
129 |
130 | $signature = JWT::sign($signing_input, $key, $alg);
131 | $segments[] = JWT::urlsafeB64Encode($signature);
132 |
133 | return implode('.', $segments);
134 | }
135 |
136 | /**
137 | * Sign a string with a given key and algorithm.
138 | *
139 | * @param string $msg The message to sign
140 | * @param string|resource $key The secret key
141 | * @param string $alg The signing algorithm. Supported algorithms
142 | * are 'HS256', 'HS384', 'HS512' and 'RS256'
143 | *
144 | * @return string An encrypted message
145 | * @throws DomainException Unsupported algorithm was specified
146 | */
147 | public static function sign($msg, $key, $alg = 'HS256')
148 | {
149 | if (empty(self::$supported_algs[$alg])) {
150 | throw new DomainException('Algorithm not supported');
151 | }
152 | list($function, $algorithm) = self::$supported_algs[$alg];
153 | switch($function) {
154 | case 'hash_hmac':
155 | return hash_hmac($algorithm, $msg, $key, true);
156 | case 'openssl':
157 | $signature = '';
158 | $success = openssl_sign($msg, $signature, $key, $algorithm);
159 | if (!$success) {
160 | throw new DomainException("OpenSSL unable to sign data");
161 | } else {
162 | return $signature;
163 | }
164 | }
165 | }
166 |
167 | /**
168 | * Verify a signature with the mesage, key and method. Not all methods
169 | * are symmetric, so we must have a separate verify and sign method.
170 | * @param string $msg the original message
171 | * @param string $signature
172 | * @param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public key
173 | * @param string $alg
174 | * @return bool
175 | * @throws DomainException Invalid Algorithm or OpenSSL failure
176 | */
177 | private static function verify($msg, $signature, $key, $alg)
178 | {
179 | if (empty(self::$supported_algs[$alg])) {
180 | throw new DomainException('Algorithm not supported');
181 | }
182 |
183 | list($function, $algorithm) = self::$supported_algs[$alg];
184 | switch($function) {
185 | case 'openssl':
186 | $success = openssl_verify($msg, $signature, $key, $algorithm);
187 | if (!$success) {
188 | throw new DomainException("OpenSSL unable to verify data: " . openssl_error_string());
189 | } else {
190 | return $signature;
191 | }
192 | case 'hash_hmac':
193 | default:
194 | $hash = hash_hmac($algorithm, $msg, $key, true);
195 | if (function_exists('hash_equals')) {
196 | return hash_equals($signature, $hash);
197 | }
198 | $len = min(self::safeStrlen($signature), self::safeStrlen($hash));
199 |
200 | $status = 0;
201 | for ($i = 0; $i < $len; $i++) {
202 | $status |= (ord($signature[$i]) ^ ord($hash[$i]));
203 | }
204 | $status |= (self::safeStrlen($signature) ^ self::safeStrlen($hash));
205 |
206 | return ($status === 0);
207 | }
208 | }
209 |
210 | /**
211 | * Decode a JSON string into a PHP object.
212 | *
213 | * @param string $input JSON string
214 | *
215 | * @return object Object representation of JSON string
216 | * @throws DomainException Provided string was invalid JSON
217 | */
218 | public static function jsonDecode($input)
219 | {
220 | if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
221 | /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
222 | * to specify that large ints (like Steam Transaction IDs) should be treated as
223 | * strings, rather than the PHP default behaviour of converting them to floats.
224 | */
225 | $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
226 | } else {
227 | /** Not all servers will support that, however, so for older versions we must
228 | * manually detect large ints in the JSON string and quote them (thus converting
229 | *them to strings) before decoding, hence the preg_replace() call.
230 | */
231 | $max_int_length = strlen((string) PHP_INT_MAX) - 1;
232 | $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
233 | $obj = json_decode($json_without_bigints);
234 | }
235 |
236 | if (function_exists('json_last_error') && $errno = json_last_error()) {
237 | JWT::handleJsonError($errno);
238 | } elseif ($obj === null && $input !== 'null') {
239 | throw new DomainException('Null result with non-null input');
240 | }
241 | return $obj;
242 | }
243 |
244 | /**
245 | * Encode a PHP object into a JSON string.
246 | *
247 | * @param object|array $input A PHP object or array
248 | *
249 | * @return string JSON representation of the PHP object or array
250 | * @throws DomainException Provided object could not be encoded to valid JSON
251 | */
252 | public static function jsonEncode($input)
253 | {
254 | $json = json_encode($input);
255 | if (function_exists('json_last_error') && $errno = json_last_error()) {
256 | JWT::handleJsonError($errno);
257 | } elseif ($json === 'null' && $input !== null) {
258 | throw new DomainException('Null result with non-null input');
259 | }
260 | return $json;
261 | }
262 |
263 | /**
264 | * Decode a string with URL-safe Base64.
265 | *
266 | * @param string $input A Base64 encoded string
267 | *
268 | * @return string A decoded string
269 | */
270 | public static function urlsafeB64Decode($input)
271 | {
272 | $remainder = strlen($input) % 4;
273 | if ($remainder) {
274 | $padlen = 4 - $remainder;
275 | $input .= str_repeat('=', $padlen);
276 | }
277 | return base64_decode(strtr($input, '-_', '+/'));
278 | }
279 |
280 | /**
281 | * Encode a string with URL-safe Base64.
282 | *
283 | * @param string $input The string you want encoded
284 | *
285 | * @return string The base64 encode of what you passed in
286 | */
287 | public static function urlsafeB64Encode($input)
288 | {
289 | return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
290 | }
291 |
292 | /**
293 | * Helper method to create a JSON error.
294 | *
295 | * @param int $errno An error number from json_last_error()
296 | *
297 | * @return void
298 | */
299 | private static function handleJsonError($errno)
300 | {
301 | $messages = array(
302 | JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
303 | JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
304 | JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON'
305 | );
306 | throw new DomainException(
307 | isset($messages[$errno])
308 | ? $messages[$errno]
309 | : 'Unknown JSON error: ' . $errno
310 | );
311 | }
312 |
313 | /**
314 | * Get the number of bytes in cryptographic strings.
315 | *
316 | * @param string
317 | * @return int
318 | */
319 | private static function safeStrlen($str)
320 | {
321 | if (function_exists('mb_strlen')) {
322 | return mb_strlen($str, '8bit');
323 | }
324 | return strlen($str);
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/lib/php-jwt/Exceptions/BeforeValidException.php:
--------------------------------------------------------------------------------
1 | "http://example.org",
25 | "aud" => "http://example.com",
26 | "iat" => 1356999524,
27 | "nbf" => 1357000000
28 | );
29 |
30 | /**
31 | * IMPORTANT:
32 | * You must specify supported algorithms for your application. See
33 | * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
34 | * for a list of spec-compliant algorithms.
35 | */
36 | $jwt = JWT::encode($token, $key);
37 | $decoded = JWT::decode($jwt, $key, array('HS256'));
38 |
39 | print_r($decoded);
40 |
41 | /*
42 | NOTE: This will now be an object instead of an associative array. To get
43 | an associative array, you will need to cast it as such:
44 | */
45 |
46 | $decoded_array = (array) $decoded;
47 |
48 | ?>
49 | ```
50 |
51 | Changelog
52 | ---------
53 |
54 | #### 2.0.0 / 2015-04-01
55 | - **Note**: It is strongly recommended that you update to > v2.0.0 to address
56 | known security vulnerabilities in prior versions when both symmetric and
57 | asymmetric keys are used together.
58 | - Update signature for `JWT::decode(...)` to require an array of supported
59 | algorithms to use when verifying token signatures.
60 |
61 |
62 | Tests
63 | -----
64 | Run the tests using phpunit:
65 |
66 | ```bash
67 | $ pear install PHPUnit
68 | $ phpunit --configuration phpunit.xml.dist
69 | PHPUnit 3.7.10 by Sebastian Bergmann.
70 | .....
71 | Time: 0 seconds, Memory: 2.50Mb
72 | OK (5 tests, 5 assertions)
73 | ```
74 |
75 | License
76 | -------
77 | [3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
78 |
--------------------------------------------------------------------------------
/lib/php-jwt/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "firebase/php-jwt",
3 | "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
4 | "homepage": "https://github.com/firebase/php-jwt",
5 | "authors": [
6 | {
7 | "name": "Neuman Vong",
8 | "email": "neuman+pear@twilio.com",
9 | "role": "Developer"
10 | },
11 | {
12 | "name": "Anant Narayanan",
13 | "email": "anant@php.net",
14 | "role": "Developer"
15 | }
16 | ],
17 | "license": "BSD-3-Clause",
18 | "require": {
19 | "php": ">=5.2.0"
20 | },
21 | "autoload": {
22 | "classmap": ["Authentication/", "Exceptions/"]
23 | },
24 | "minimum-stability": "dev"
25 | }
26 |
--------------------------------------------------------------------------------
/lib/php-jwt/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | JWT
7 | pear.php.net
8 | A JWT encoder/decoder.
9 | A JWT encoder/decoder library for PHP.
10 |
11 | Neuman Vong
12 | lcfrs
13 | neuman+pear@twilio.com
14 | yes
15 |
16 |
17 | Anant Narayanan
18 | anant
19 | anant@php.net
20 | yes
21 |
22 | 2015-04-01
23 |
24 | 2.0.0
25 | 2.0.0
26 |
27 |
28 | beta
29 | beta
30 |
31 | BSD 3-Clause License
32 |
33 | Initial release with basic support for JWT encoding, decoding and signature verification.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 5.1
47 |
48 |
49 | 1.7.0
50 |
51 |
52 | json
53 |
54 |
55 | hash
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 0.1.0
64 | 0.1.0
65 |
66 |
67 | beta
68 | beta
69 |
70 | 2015-04-01
71 | BSD 3-Clause License
72 |
73 | Initial release with basic support for JWT encoding, decoding and signature verification.
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/lib/php-jwt/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 | ./tests
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lib/php-jwt/run-tests.sh:
--------------------------------------------------------------------------------
1 |
2 | #!/usr/bin/env bash
3 | gpg --fingerprint D8406D0D82947747293778314AA394086372C20A
4 | if [ $? -ne 0 ]; then
5 | echo -e "\033[33mDownloading PGP Public Key...\033[0m"
6 | gpg --recv-keys D8406D0D82947747293778314AA394086372C20A
7 | # Sebastian Bergmann
8 | gpg --fingerprint D8406D0D82947747293778314AA394086372C20A
9 | if [ $? -ne 0 ]; then
10 | echo -e "\033[31mCould not download PGP public key for verification\033[0m"
11 | exit
12 | fi
13 | fi
14 |
15 | # Let's grab the latest release and its signature
16 | if [ ! -f phpunit.phar ]; then
17 | wget https://phar.phpunit.de/phpunit.phar
18 | fi
19 | if [ ! -f phpunit.phar.asc ]; then
20 | wget https://phar.phpunit.de/phpunit.phar.asc
21 | fi
22 |
23 | # Verify before running
24 | gpg --verify phpunit.phar.asc phpunit.phar
25 | if [ $? -eq 0 ]; then
26 | echo
27 | echo -e "\033[33mBegin Unit Testing\033[0m"
28 | # Run the testing suite
29 | php --version
30 | php phpunit.phar --configuration phpunit.xml.dist
31 | else
32 | echo
33 | chmod -x phpunit.phar
34 | mv phpunit.phar /tmp/bad-phpunit.phar
35 | mv phpunit.phar.asc /tmp/bad-phpunit.phar.asc
36 | echo -e "\033[31mSignature did not match! PHPUnit has been moved to /tmp/bad-phpunit.phar\033[0m"
37 | exit 1
38 | fi
39 |
--------------------------------------------------------------------------------
/lib/php-jwt/tests/JWTTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(JWT::decode($msg, 'my_key', array('HS256')), 'abc');
9 | }
10 |
11 | public function testDecodeFromPython()
12 | {
13 | $msg = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.Iio6aHR0cDovL2FwcGxpY2F0aW9uL2NsaWNreT9ibGFoPTEuMjMmZi5vbz00NTYgQUMwMDAgMTIzIg.E_U8X2YpMT5K1cEiT_3-IvBYfrdIFIeVYeOqre_Z5Cg';
14 | $this->assertEquals(
15 | JWT::decode($msg, 'my_key', array('HS256')),
16 | '*:http://application/clicky?blah=1.23&f.oo=456 AC000 123'
17 | );
18 | }
19 |
20 | public function testUrlSafeCharacters()
21 | {
22 | $encoded = JWT::encode('f?', 'a');
23 | $this->assertEquals('f?', JWT::decode($encoded, 'a', array('HS256')));
24 | }
25 |
26 | public function testMalformedUtf8StringsFail()
27 | {
28 | $this->setExpectedException('DomainException');
29 | JWT::encode(pack('c', 128), 'a');
30 | }
31 |
32 | public function testMalformedJsonThrowsException()
33 | {
34 | $this->setExpectedException('DomainException');
35 | JWT::jsonDecode('this is not valid JSON string');
36 | }
37 |
38 | public function testExpiredToken()
39 | {
40 | $this->setExpectedException('ExpiredException');
41 | $payload = array(
42 | "message" => "abc",
43 | "exp" => time() - 20); // time in the past
44 | $encoded = JWT::encode($payload, 'my_key');
45 | JWT::decode($encoded, 'my_key', array('HS256'));
46 | }
47 |
48 | public function testBeforeValidTokenWithNbf()
49 | {
50 | $this->setExpectedException('BeforeValidException');
51 | $payload = array(
52 | "message" => "abc",
53 | "nbf" => time() + 20); // time in the future
54 | $encoded = JWT::encode($payload, 'my_key');
55 | JWT::decode($encoded, 'my_key', array('HS256'));
56 | }
57 |
58 | public function testBeforeValidTokenWithIat()
59 | {
60 | $this->setExpectedException('BeforeValidException');
61 | $payload = array(
62 | "message" => "abc",
63 | "iat" => time() + 20); // time in the future
64 | $encoded = JWT::encode($payload, 'my_key');
65 | JWT::decode($encoded, 'my_key', array('HS256'));
66 | }
67 |
68 | public function testValidToken()
69 | {
70 | $payload = array(
71 | "message" => "abc",
72 | "exp" => time() + 20); // time in the future
73 | $encoded = JWT::encode($payload, 'my_key');
74 | $decoded = JWT::decode($encoded, 'my_key', array('HS256'));
75 | $this->assertEquals($decoded->message, 'abc');
76 | }
77 |
78 | public function testValidTokenWithList()
79 | {
80 | $payload = array(
81 | "message" => "abc",
82 | "exp" => time() + 20); // time in the future
83 | $encoded = JWT::encode($payload, 'my_key');
84 | $decoded = JWT::decode($encoded, 'my_key', array('HS256', 'HS512'));
85 | $this->assertEquals($decoded->message, 'abc');
86 | }
87 |
88 | public function testValidTokenWithNbf()
89 | {
90 | $payload = array(
91 | "message" => "abc",
92 | "iat" => time(),
93 | "exp" => time() + 20, // time in the future
94 | "nbf" => time() - 20);
95 | $encoded = JWT::encode($payload, 'my_key');
96 | $decoded = JWT::decode($encoded, 'my_key', array('HS256'));
97 | $this->assertEquals($decoded->message, 'abc');
98 | }
99 |
100 | public function testInvalidToken()
101 | {
102 | $payload = array(
103 | "message" => "abc",
104 | "exp" => time() + 20); // time in the future
105 | $encoded = JWT::encode($payload, 'my_key');
106 | $this->setExpectedException('SignatureInvalidException');
107 | $decoded = JWT::decode($encoded, 'my_key2', array('HS256'));
108 | }
109 |
110 | public function testRSEncodeDecode()
111 | {
112 | $privKey = openssl_pkey_new(array('digest_alg' => 'sha256',
113 | 'private_key_bits' => 1024,
114 | 'private_key_type' => OPENSSL_KEYTYPE_RSA));
115 | $msg = JWT::encode('abc', $privKey, 'RS256');
116 | $pubKey = openssl_pkey_get_details($privKey);
117 | $pubKey = $pubKey['key'];
118 | $decoded = JWT::decode($msg, $pubKey, array('RS256'));
119 | $this->assertEquals($decoded, 'abc');
120 | }
121 |
122 | public function testKIDChooser()
123 | {
124 | $keys = array('1' => 'my_key', '2' => 'my_key2');
125 | $msg = JWT::encode('abc', $keys['1'], 'HS256', '1');
126 | $decoded = JWT::decode($msg, $keys, array('HS256'));
127 | $this->assertEquals($decoded, 'abc');
128 | }
129 |
130 | public function testNoneAlgorithm()
131 | {
132 | $msg = JWT::encode('abc', 'my_key');
133 | $this->setExpectedException('DomainException');
134 | JWT::decode($msg, 'my_key', array('none'));
135 | }
136 |
137 | public function testIncorrectAlgorithm()
138 | {
139 | $msg = JWT::encode('abc', 'my_key');
140 | $this->setExpectedException('DomainException');
141 | JWT::decode($msg, 'my_key', array('RS256'));
142 | }
143 |
144 | public function testMissingAlgorithm()
145 | {
146 | $msg = JWT::encode('abc', 'my_key');
147 | $this->setExpectedException('DomainException');
148 | JWT::decode($msg, 'my_key');
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/lib/php-jwt/tests/autoload.php.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------