JWT Authentication for WP REST API - Version 1.2.0

Version Description

  • Tested with 4.4.2
Download this release

Release Info

Developer Tmeister
Plugin Icon JWT Authentication for WP REST API
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.0.0 to 1.2.0

README.md CHANGED
@@ -1,8 +1,8 @@
1
  # JWT Authentication for the WP REST API
2
 
3
- A simple plugin to add [JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) Authentication to WP REST API.
4
 
5
- To know more about the JSON Web Tokens, please visit [http://jwt.io](http://jwt.io).
6
 
7
  ## Requirements
8
 
@@ -16,13 +16,13 @@ So, to use the **wp-api-jwt-auth** you need to install and activate [WP REST API
16
 
17
  **Minimum PHP version: 5.3.0**
18
 
19
- ### PHP HTTP Authorization Header enable
20
 
21
- #### Shared Hostings
22
 
23
- Most of the shared hosting has disabled the **HTTP Authorization Header** by default.
24
 
25
- To enable this option you'll need to edit your **.htaccess** file adding the follow
26
 
27
  ```
28
  RewriteEngine on
@@ -32,9 +32,7 @@ RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
32
 
33
  #### WPEngine
34
 
35
- To enable this option you'll need to edit your **.htaccess** file adding the follow
36
-
37
- See https://github.com/Tmeister/wp-api-jwt-auth/issues/1
38
 
39
  ```
40
  SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
@@ -42,15 +40,15 @@ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
42
 
43
  ## Installation & Configuration
44
 
45
- [Download the zip file](https://github.com/Tmeister/wp-api-jwt-auth/archive/master.zip) and install it as any other WordPress plugin.
46
 
47
- Or clone this repo into your WordPress installation under the wp-content/plugins folder.
48
 
49
  ### Configurate the Secret Key
50
 
51
- The JWT needs a **secret key** to sign the token this **secret key** must be unique and never revealed.
52
 
53
- To add the **secret key** edit your wp-config.php file and add a new constant called **JWT_AUTH_SECRET_KEY**
54
 
55
 
56
  ```php
@@ -71,11 +69,11 @@ define('JWT_AUTH_CORS_ENABLE', true);
71
  ```
72
 
73
 
74
- Finally activate the plugin within your wp-admin.
75
 
76
  ## Namespace and Endpoints
77
 
78
- When the plugin is activated, a new namespace is added
79
 
80
 
81
  ```
@@ -83,7 +81,7 @@ When the plugin is activated, a new namespace is added
83
  ```
84
 
85
 
86
- Also, two new endpoints are added to this namespace
87
 
88
 
89
  Endpoint | HTTP Verb
@@ -129,7 +127,7 @@ Validates the user credentials, *username* and *password*, and returns a token t
129
 
130
  ```
131
 
132
- Success response from the server
133
 
134
  ```json
135
  {
@@ -140,7 +138,7 @@ Success response from the server
140
  }
141
  ```
142
 
143
- Error response from the server
144
 
145
  ```json
146
  {
@@ -152,11 +150,11 @@ Error response from the server
152
  }
153
  ```
154
 
155
- Once you get the token, you must store it somewhere in your application, ex. in a **cookie** or using **localstorage**.
156
 
157
- From this point, you should pass this token to every API call
158
 
159
- Sample call using the Authorization header using AngularJS
160
 
161
  ```javascript
162
  app.config( function( $httpProvider ) {
@@ -178,7 +176,7 @@ app.config( function( $httpProvider ) {
178
  } );
179
  ```
180
 
181
- The **wp-api-jwt-auth** will intercept every call to the server and will look for the Authorization Header, if the Authorization header is present will try to decode the token and will set the user according with the data stored in it.
182
 
183
  If the token is valid, the API call flow will continue as always.
184
 
@@ -192,7 +190,7 @@ Authorization: Bearer mF_s9.B5f-4.1JqM
192
 
193
  ###Errors
194
 
195
- If the token is invalid an error will be returned, here are some samples of errors.
196
 
197
  **Invalid Credentials**
198
 
@@ -240,7 +238,7 @@ If the token is invalid an error will be returned, here are some samples of erro
240
 
241
  This is a simple helper endpoint to validate a token; you only will need to make a POST request sending the Authorization header.
242
 
243
- Valid Token Response
244
 
245
  ```json
246
  {
@@ -289,7 +287,7 @@ time() + (DAY_IN_SECONDS * 7)
289
 
290
  The **jwt_auth_token_before_sign** allows you to modify all the token data before to be encoded and signed.
291
 
292
- Default Value
293
 
294
  ```php
295
  <?php
@@ -309,7 +307,7 @@ $token = array(
309
  ###jwt_auth_token_before_dispatch
310
  The **jwt_auth_token_before_dispatch** allows you to modify all the response array before to dispatch it to the client.
311
 
312
- Default Value:
313
 
314
  ```php
315
  <?php
@@ -326,5 +324,5 @@ $data = array(
326
 
327
  [PHP-JWT from firebase](https://github.com/firebase/php-jwt)
328
 
329
- ##Licence
330
  [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
1
  # JWT Authentication for the WP REST API
2
 
3
+ A simple plugin to add [JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) Authentication to the WP REST API.
4
 
5
+ To know more about JSON Web Tokens, please visit [http://jwt.io](http://jwt.io).
6
 
7
  ## Requirements
8
 
16
 
17
  **Minimum PHP version: 5.3.0**
18
 
19
+ ### Eable PHP HTTP Authorization Header
20
 
21
+ #### Shared Hosts
22
 
23
+ Most of the shared hosts have disabled the **HTTP Authorization Header** by default.
24
 
25
+ To enable this option you'll need to edit your **.htaccess** file by adding the following:
26
 
27
  ```
28
  RewriteEngine on
32
 
33
  #### WPEngine
34
 
35
+ To enable this option you'll need to edit your **.htaccess** file by adding the following (see https://github.com/Tmeister/wp-api-jwt-auth/issues/1):
 
 
36
 
37
  ```
38
  SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
40
 
41
  ## Installation & Configuration
42
 
43
+ [Download the zip file](https://github.com/Tmeister/wp-api-jwt-auth/archive/master.zip) and install it like any other WordPress plugin.
44
 
45
+ Or clone this repo into your WordPress installation into the wp-content/plugins folder.
46
 
47
  ### Configurate the Secret Key
48
 
49
+ The JWT needs a **secret key** to sign the token. This **secret key** must be unique and never revealed.
50
 
51
+ To add the **secret key**, edit your wp-config.php file and add a new constant called **JWT_AUTH_SECRET_KEY**.
52
 
53
 
54
  ```php
69
  ```
70
 
71
 
72
+ Finally activate the plugin within the plugin dashboard.
73
 
74
  ## Namespace and Endpoints
75
 
76
+ When the plugin is activated, a new namespace is added.
77
 
78
 
79
  ```
81
  ```
82
 
83
 
84
+ Also, two new endpoints are added to this namespace.
85
 
86
 
87
  Endpoint | HTTP Verb
127
 
128
  ```
129
 
130
+ Success response from the server:
131
 
132
  ```json
133
  {
138
  }
139
  ```
140
 
141
+ Error response from the server:
142
 
143
  ```json
144
  {
150
  }
151
  ```
152
 
153
+ Once you get the token, you must store it somewhere in your application, e.g. in a **cookie** or using **localstorage**.
154
 
155
+ From this point, you should pass this token to every API call.
156
 
157
+ Sample call using the Authorization header using AngularJS:
158
 
159
  ```javascript
160
  app.config( function( $httpProvider ) {
176
  } );
177
  ```
178
 
179
+ The **wp-api-jwt-auth** will intercept every call to the server and will look for the authorization header, if the authorization header is present, it will try to decode the token and will set the user according with the data stored in it.
180
 
181
  If the token is valid, the API call flow will continue as always.
182
 
190
 
191
  ###Errors
192
 
193
+ If the token is invalid an error will be returned. Here are some samples of errors:
194
 
195
  **Invalid Credentials**
196
 
238
 
239
  This is a simple helper endpoint to validate a token; you only will need to make a POST request sending the Authorization header.
240
 
241
+ Valid Token Response:
242
 
243
  ```json
244
  {
287
 
288
  The **jwt_auth_token_before_sign** allows you to modify all the token data before to be encoded and signed.
289
 
290
+ Default value:
291
 
292
  ```php
293
  <?php
307
  ###jwt_auth_token_before_dispatch
308
  The **jwt_auth_token_before_dispatch** allows you to modify all the response array before to dispatch it to the client.
309
 
310
+ Default value:
311
 
312
  ```php
313
  <?php
324
 
325
  [PHP-JWT from firebase](https://github.com/firebase/php-jwt)
326
 
327
+ ##License
328
  [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
includes/vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) 2015 Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
includes/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname(dirname($vendorDir));
7
+
8
+ return array(
9
+ 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
10
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
11
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
12
+ );
jwt-auth.php CHANGED
@@ -15,7 +15,7 @@
15
  * Plugin Name: JWT Authentication for WP-API
16
  * Plugin URI: https://enriquechavez.co
17
  * Description: Extends the WP REST API using JSON Web Tokens Authentication as an authentication method.
18
- * Version: 1.0.0
19
  * Author: Enrique Chavez
20
  * Author URI: https://enriquechavez.co
21
  * License: GPL-2.0+
15
  * Plugin Name: JWT Authentication for WP-API
16
  * Plugin URI: https://enriquechavez.co
17
  * Description: Extends the WP REST API using JSON Web Tokens Authentication as an authentication method.
18
+ * Version: 1.2.0
19
  * Author: Enrique Chavez
20
  * Author URI: https://enriquechavez.co
21
  * License: GPL-2.0+
readme.txt CHANGED
@@ -4,8 +4,8 @@ Contributors: tmeister
4
  Donate link: https://enriquechavez.co
5
  Tags: wp-json, jwt, json web authentication, wp-api
6
  Requires at least: 4.2
7
- Tested up to: 4.3
8
- Stable tag: 1.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -340,8 +340,13 @@ $data = array(
340
  ###Please read how to configured the plugin https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/
341
 
342
  == Changelog ==
 
 
 
343
  = 1.0.0 =
344
  * Initial Release.
345
 
 
 
346
  == Upgrade Notice ==
347
  .
4
  Donate link: https://enriquechavez.co
5
  Tags: wp-json, jwt, json web authentication, wp-api
6
  Requires at least: 4.2
7
+ Tested up to: 4.4.2
8
+ Stable tag: 1.2.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
340
  ###Please read how to configured the plugin https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/
341
 
342
  == Changelog ==
343
+ = 1.2.0 =
344
+ * Tested with 4.4.2
345
+
346
  = 1.0.0 =
347
  * Initial Release.
348
 
349
+
350
+
351
  == Upgrade Notice ==
352
  .
tests/GeneralTest.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class GeneralTest extends PHPUnit_Framework_TestCase
4
+ {
5
+ protected $baseUrl = 'http://jwt.dev/';
6
+ protected $client;
7
+
8
+ protected function setUp()
9
+ {
10
+ $this->client = new GuzzleHttp\Client([
11
+ 'base_uri' => $this->baseUrl
12
+ ]);
13
+ }
14
+
15
+ /**
16
+ * Load the site and look for a Status Code Equal to 200
17
+ */
18
+ public function test_is_site_up()
19
+ {
20
+ $response = $this->client->get('/');
21
+ $this->assertEquals(200, $response->getStatusCode());
22
+ }
23
+
24
+ /**
25
+ * Look for the wp-json endpoint and look for basic data.
26
+ */
27
+ public function test_is_wp_api_installed()
28
+ {
29
+ $response = $this->client->get('wp-json/');
30
+ $this->assertEquals(200, $response->getStatusCode());
31
+ $data = json_decode($response->getBody(), true);
32
+ $this->assertArrayHasKey('namespaces', $data);
33
+ $this->assertArrayHasKey('authentication', $data);
34
+ $this->assertArrayHasKey('routes', $data);
35
+ }
36
+
37
+ /**
38
+ * Check for the jwt-auth/v1 endpoint and
39
+ */
40
+ public function test_is_jwt_installed()
41
+ {
42
+ $response = $this->client->get('wp-json/jwt-auth/v1/');
43
+ $this->assertEquals(200, $response->getStatusCode());
44
+ $data = json_decode($response->getBody(), true);
45
+ $this->assertEquals('jwt-auth/v1', $data['namespace']);
46
+ }
47
+
48
+ /**
49
+ * Get the user token
50
+ */
51
+ public function test_get_jwt_token()
52
+ {
53
+ $response = $this->client->post('wp-json/jwt-auth/v1/token', [
54
+ 'json' => [
55
+ 'username' => 'admin',
56
+ 'password' => 'poipoipoi'
57
+ ]
58
+ ]);
59
+ $this->assertEquals(200, $response->getStatusCode());
60
+ $data = json_decode($response->getBody(), true);
61
+ $this->assertArrayHasKey('token', $data);
62
+ $this->assertArrayHasKey('token', $data);
63
+ $this->assertArrayHasKey('user_email', $data);
64
+ $this->assertNotEmpty($data['token']);
65
+ $this->assertNotEmpty($data['user_email']);
66
+ }
67
+
68
+ /**
69
+ * Get the Token and then validate...
70
+ */
71
+ public function test_validate_jwt_token()
72
+ {
73
+ $token = '';
74
+ #first get a valid token.
75
+ $response = $this->client->post('wp-json/jwt-auth/v1/token', [
76
+ 'json' => [
77
+ 'username' => 'admin',
78
+ 'password' => 'poipoipoi'
79
+ ]
80
+ ]);
81
+ $this->assertEquals(200, $response->getStatusCode());
82
+ $data = json_decode($response->getBody(), true);
83
+ $token = $data['token'];
84
+
85
+ #With the token now validate it.
86
+ $response = $this->client->post('wp-json/jwt-auth/v1/token/validate', [
87
+ 'headers' => [
88
+ 'Authorization' => 'Bearer ' . $token
89
+ ]
90
+ ]);
91
+ $this->assertEquals(200, $response->getStatusCode());
92
+ $data = json_decode($response->getBody(), true);
93
+ $this->assertArrayHasKey('code', $data);
94
+ $this->assertArrayHasKey('data', $data);
95
+ $this->assertEquals(200, $data['data']['status']);
96
+
97
+ #Finally get the me | Reading
98
+ $response = $this->client->get('wp-json/wp/v2/users/me', [
99
+ 'headers' => [
100
+ 'Authorization' => 'Bearer ' . $token
101
+ ]
102
+ ]);
103
+
104
+ $this->assertEquals(200, $response->getStatusCode());
105
+ $data = json_decode($response->getBody(), true);
106
+ $this->assertArrayHasKey('id', $data);
107
+ $this->assertArrayHasKey('name', $data);
108
+ }
109
+
110
+ /**
111
+ * Try to Write a Post | Write Permissions
112
+ */
113
+ public function test_jwt_write_access()
114
+ {
115
+ #first get a valid token.
116
+ $response = $this->client->post('wp-json/jwt-auth/v1/token', [
117
+ 'json' => [
118
+ 'username' => 'admin',
119
+ 'password' => 'poipoipoi'
120
+ ]
121
+ ]);
122
+ $this->assertEquals(200, $response->getStatusCode());
123
+ $data = json_decode($response->getBody(), true);
124
+ $token = $data['token'];
125
+
126
+ #Create the post | Writing
127
+ $response = $this->client->post('wp-json/wp/v2/posts', [
128
+ 'headers' => [
129
+ 'Authorization' => 'Bearer ' . $token
130
+ ],
131
+ 'json' => [
132
+ 'title' => 'Created from Tests'
133
+ ]
134
+ ]);
135
+
136
+ $this->assertEquals(201, $response->getStatusCode());
137
+ $data = json_decode($response->getBody(), true);
138
+ #201 is created and now look and get the new post ID
139
+ $this->assertArrayHasKey('id', $data);
140
+ $post_id = $data['id'];
141
+
142
+ #Delete the test post
143
+ #Finally get the me | Reading
144
+ $response = $this->client->delete('wp-json/wp/v2/posts/' . $post_id, [
145
+ 'headers' => [
146
+ 'Authorization' => 'Bearer ' . $token
147
+ ]
148
+ ]);
149
+ $this->assertEquals(200, $response->getStatusCode());
150
+ $data = json_decode($response->getBody(), true);
151
+ $this->assertArrayHasKey('id', $data);
152
+ //The post ID must to be the same as the created one.
153
+ $this->assertEquals($post_id, $data['id']);
154
+ }
155
+ }