PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | inc/jwt/includes/class-jwt-public.php +402 -392 4.3.9 → 4.4.9 View file →
@@ -1,392 +1,402 @@
1 -<?php
2 -
3 -use LP\Firebase\JWT\JWT;
4 -
5 -/**
6 - * REST API: LP_Jwt_Public
7 - *
8 - * @package LPJWTAuth
9 - * @since 1.0.0
10 - * @author Nhamdv <[email protected]>
11 - */
12 -
13 -class LP_Jwt_Public {
14 - private $name;
15 -
16 - private $version;
17 -
18 - private $namespace;
19 -
20 - private $jwt_error;
21 -
22 - private $secret_key;
23 -
24 - public function __construct( $name, $version ) {
25 - $this->name = $name;
26 - $this->version = $version;
27 - $this->namespace = $this->name . '/' . $this->version;
28 -
29 - if ( ! defined( 'SECURE_AUTH_KEY' ) && ! defined( 'LP_SECURE_AUTH_KEY' ) ) {
30 - return;
31 - }
32 -
33 - $this->secret_key = defined( 'LP_SECURE_AUTH_KEY' ) ? LP_SECURE_AUTH_KEY : SECURE_AUTH_KEY;
34 - }
35 -
36 - public function register_routes() {
37 - register_rest_route(
38 - $this->namespace,
39 - 'token',
40 - array(
41 - 'methods' => WP_REST_Server::CREATABLE,
42 - 'callback' => array( $this, 'generate_token' ),
43 - 'args' => array(
44 - 'username' => array(
45 - 'description' => esc_html__( 'The username of the user.', 'learnpress' ),
46 - 'type' => 'string',
47 - 'sanitize_callback' => 'sanitize_text_field',
48 - 'validate_callback' => 'rest_validate_request_arg',
49 - ),
50 - 'password' => array(
51 - 'description' => esc_html__( 'The password of the user.', 'learnpress' ),
52 - 'type' => 'string',
53 - 'sanitize_callback' => 'sanitize_text_field',
54 - 'validate_callback' => 'rest_validate_request_arg',
55 - ),
56 - ),
57 - 'schema' => array( $this, 'get_item_schema' ),
58 - 'permission_callback' => '__return_true',
59 - )
60 - );
61 -
62 - register_rest_route(
63 - $this->namespace,
64 - 'token/validate',
65 - array(
66 - 'methods' => WP_REST_Server::CREATABLE,
67 - 'callback' => array( $this, 'validate_token' ),
68 - 'permission_callback' => '__return_true',
69 - )
70 - );
71 -
72 - register_rest_route(
73 - $this->namespace,
74 - 'token/register',
75 - array(
76 - 'methods' => WP_REST_Server::CREATABLE,
77 - 'callback' => array( $this, 'register' ),
78 - 'permission_callback' => '__return_true',
79 - )
80 - );
81 - }
82 -
83 - public function get_item_schema() {
84 - $schema = array(
85 - '$schema' => 'http://json-schema.org/draft-04/schema#',
86 - 'title' => esc_html__( 'JSON Web Token', 'learnpress' ),
87 - 'type' => 'object',
88 - 'properties' => array(
89 - 'token' => array(
90 - 'description' => esc_html__( 'JSON Web Token.', 'learnpress' ),
91 - 'type' => 'string',
92 - 'readonly' => true,
93 - ),
94 - 'user_id' => array(
95 - 'description' => esc_html__( 'The ID of the user.', 'learnpress' ),
96 - 'type' => 'integer',
97 - 'readonly' => true,
98 - ),
99 - 'user_login' => array(
100 - 'description' => esc_html__( 'The username of the user', 'learnpress' ),
101 - 'type' => 'string',
102 - 'readonly' => true,
103 - ),
104 - 'user_email' => array(
105 - 'description' => esc_html__( 'The email address of the user.', 'learnpress' ),
106 - 'type' => 'string',
107 - 'readonly' => true,
108 - ),
109 - ),
110 - );
111 -
112 - return apply_filters( 'lp_rest_authentication_token_schema', $schema );
113 - }
114 -
115 - /**
116 - * Add CORs support to the request.
117 - */
118 - public function add_cors_support() {
119 - $enable_cors = defined( 'LP_JWT_AUTH_CORS_ENABLE' ) ? LP_JWT_AUTH_CORS_ENABLE : false;
120 -
121 - if ( $enable_cors ) {
122 - $headers = apply_filters( 'lp_jwt_auth_cors_allow_headers', 'Access-Control-Allow-Headers, Content-Type, Authorization' );
123 - header( sprintf( 'Access-Control-Allow-Headers: %s', $headers ) );
124 - }
125 - }
126 -
127 - public function register( WP_REST_Request $request ) {
128 - $username = $request->get_param( 'username' );
129 - $password = $request->get_param( 'password' );
130 - $confirm_password = $request->get_param( 'confirm_password' );
131 - $email = $request->get_param( 'email' );
132 -
133 - $customer_id = LP_Forms_Handler::learnpress_create_new_customer( $email, $username, $password, $confirm_password );
134 -
135 - if ( is_wp_error( $customer_id ) ) {
136 - return new WP_Error(
137 - $customer_id->get_error_code(),
138 - $customer_id->get_error_message(),
139 - array(
140 - 'status' => 403,
141 - )
142 - );
143 - }
144 -
145 - return $this->generate_token( $request );
146 - }
147 -
148 - public function generate_token( WP_REST_Request $request ) {
149 - $secret_key = $this->secret_key;
150 - $username = $request->get_param( 'username' );
151 - $password = $request->get_param( 'password' );
152 -
153 - if ( ! $secret_key ) {
154 - return new WP_Error(
155 - 'lp_jwt_auth_bad_config',
156 - esc_html__( 'LearnPress JWT is not configurated properly, please contact the admin', 'learnpress' ),
157 - array(
158 - 'status' => 403,
159 - )
160 - );
161 - }
162 -
163 - /** Try to authenticate the user with the passed credentials*/
164 - $user = wp_authenticate( $username, $password );
165 -
166 - /** If the authentication fails return a error*/
167 - if ( is_wp_error( $user ) ) {
168 - $error_code = $user->get_error_code();
169 -
170 - return new WP_Error(
171 - '[lp_jwt_auth] ' . $error_code,
172 - $user->get_error_message( $error_code ),
173 - array(
174 - 'status' => 403,
175 - )
176 - );
177 - }
178 -
179 - /** Valid credentials, the user exists create the according Token */
180 - $issued_at = time();
181 - $not_before = apply_filters( 'lp_jwt_auth_not_before', $issued_at, $issued_at );
182 - $expire = apply_filters( 'lp_jwt_auth_expire', $issued_at + WEEK_IN_SECONDS, $issued_at );
183 -
184 - $token = array(
185 - 'iss' => get_bloginfo( 'url' ),
186 - 'iat' => $issued_at,
187 - 'nbf' => $not_before,
188 - 'exp' => $expire,
189 - 'data' => array(
190 - 'user' => array(
191 - 'id' => $user->data->ID,
192 - ),
193 - ),
194 - );
195 -
196 - /** Let the user modify the token data before the sign. */
197 - $token = JWT::encode( apply_filters( 'lp_jwt_auth_token_before_sign', $token, $user ), $secret_key );
198 -
199 - /** The token is signed, now create the object with no sensible user data to the client*/
200 - $data = array(
201 - 'token' => $token,
202 - 'user_id' => $user->data->ID,
203 - 'user_login' => $user->data->user_login,
204 - 'user_email' => $user->data->user_email,
205 - 'user_display_name' => $user->data->display_name,
206 - );
207 -
208 - return apply_filters( 'lp_jwt_auth_token_before_dispatch', $data, $user );
209 - }
210 -
211 - /**
212 - * This is our Middleware to try to authenticate the user according to the
213 - * token send.
214 - *
215 - * @param (int|bool) $user Logged User ID
216 - *
217 - * @return (int|bool)
218 - */
219 - public function determine_current_user( $user_id ) {
220 - $rest_prefix = trailingslashit( rest_get_url_prefix() );
221 - $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) );
222 - $valid_api_uri = strpos( $request_uri, $rest_prefix . $this->name . '/' );
223 -
224 - /**
225 - * Only check when rest url has wp-json/learnpress/.
226 - */
227 - if ( ! empty( $user_id ) || $valid_api_uri === false ) {
228 - return $user_id;
229 - }
230 -
231 - /*
232 - * if the request URI is for validate the token don't do anything,
233 - * this avoid double calls to the validate_token function.
234 - */
235 - $validate_token = strpos( $request_uri, '/token' );
236 -
237 - /** All course is public so donot need token */
238 - $is_rest_courses = strpos( $request_uri, '/courses' ) || strpos( $request_uri, '/reset-password' ) || strpos( $request_uri, '/course_category' ) || strpos( $request_uri, '/sections/' ) || strpos( $request_uri, '/section-items/' ) || strpos( $request_uri, '/users' );
239 -
240 - if ( $validate_token > 0 ) {
241 - return $user_id;
242 - }
243 -
244 - $token = $this->validate_token( false );
245 -
246 - if ( is_wp_error( $token ) ) {
247 - if ( ! $is_rest_courses ) {
248 - $this->jwt_error = $token;
249 - }
250 -
251 - return $user_id;
252 - }
253 -
254 - return $token->data->user->id;
255 - }
256 -
257 - public function validate_token( $output = true ) {
258 - /*
259 - * Looking for the HTTP_AUTHORIZATION header, if not present just
260 - * return the user.
261 - */
262 - $auth = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? sanitize_text_field( $_SERVER['HTTP_AUTHORIZATION'] ) : false;
263 -
264 - /* Double check for different auth header string (server dependent) */
265 - if ( ! $auth ) {
266 - $auth = isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ? sanitize_text_field( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) : false;
267 - }
268 -
269 - if ( ! $auth ) {
270 - return new WP_Error(
271 - 'lp_jwt_auth_no_auth_header',
272 - esc_html__( 'Authorization header not found.', 'learnpress' ),
273 - array(
274 - 'status' => 401,
275 - )
276 - );
277 - }
278 -
279 - /*
280 - * The HTTP_AUTHORIZATION is present verify the format
281 - * if the format is wrong return the user.
282 - */
283 - list( $token ) = sscanf( $auth, 'Bearer %s' );
284 -
285 - if ( ! $token ) {
286 - return new WP_Error(
287 - 'lp_jwt_auth_bad_auth_header',
288 - esc_html__( 'Authentication token is missing.', 'learnpress' ),
289 - array(
290 - 'status' => 401,
291 - )
292 - );
293 - }
294 -
295 - /** Get the Secret Key */
296 - $secret_key = $this->secret_key;
297 -
298 - if ( ! $secret_key ) {
299 - return new WP_Error(
300 - 'lp_jwt_auth_bad_config',
301 - esc_html__( 'LearnPress JWT is not configurated properly, please contact the admin', 'learnpress' ),
302 - array(
303 - 'status' => 401,
304 - )
305 - );
306 - }
307 -
308 - /** Try to decode the token */
309 - try {
310 - $token = JWT::decode( $token, $secret_key, array( 'HS256' ) );
311 -
312 - /** The Token is decoded now validate the iss */
313 - if ( $token->iss != get_bloginfo( 'url' ) ) {
314 - return new WP_Error(
315 - 'lp_jwt_auth_bad_iss',
316 - esc_html__( 'The iss do not match with this server', 'learnpress' ),
317 - array(
318 - 'status' => 401,
319 - )
320 - );
321 - }
322 -
323 - /** So far so good, validate the user id in the token */
324 - if ( ! isset( $token->data->user->id ) ) {
325 - return new WP_Error(
326 - 'lp_jwt_auth_bad_request',
327 - esc_html__( 'User ID not found in the token', 'learnpress' ),
328 - array(
329 - 'status' => 401,
330 - )
331 - );
332 - }
333 -
334 - if ( ! isset( $token->exp ) ) {
335 - return new WP_Error(
336 - 'rest_authentication_missing_token_expiration',
337 - esc_html__( 'The token must have an expiration date.', 'learnpress' ),
338 - array(
339 - 'status' => 401,
340 - )
341 - );
342 - }
343 -
344 - if ( time() > $token->exp ) {
345 - return new WP_Error(
346 - 'rest_authentication_token_expired',
347 - esc_html__( 'The token has expired.', 'learnpress' ),
348 - array(
349 - 'status' => 401,
350 - )
351 - );
352 - }
353 -
354 - /** Everything looks good return the decoded token if the $output is false */
355 - if ( ! $output ) {
356 - return $token;
357 - }
358 -
359 - /** If the output is true return an answer to the request to show it */
360 - return array(
361 - 'code' => 'lp_jwt_auth_valid_token',
362 - 'message' => esc_html__( 'Valid access token.', 'learnpress' ),
363 - 'data' => array(
364 - 'status' => 200,
365 - 'exp' => $token->exp - time(),
366 - ),
367 - );
368 - } catch ( Exception $e ) {
369 - return new WP_Error(
370 - 'lp_jwt_auth_invalid_token',
371 - $e->getMessage(),
372 - array(
373 - 'status' => 401,
374 - )
375 - );
376 - }
377 - }
378 -
379 - /**
380 - * Filter to hook the rest_pre_dispatch, if the is an error in the request
381 - * send it, if there is no error just continue with the current request.
382 - *
383 - * @param $request
384 - */
385 - public function rest_pre_dispatch( $request ) {
386 - if ( is_wp_error( $this->jwt_error ) ) {
387 - return $this->jwt_error;
388 - }
389 -
390 - return $request;
391 - }
392 -}
1 +<?php
2 +
3 +use LP\Firebase\JWT\JWT;
4 +
5 +/**
6 + * REST API: LP_Jwt_Public
7 + *
8 + * @package LPJWTAuth
9 + * @since 1.0.0
10 + * @author Nhamdv <[email protected]>
11 + */
12 +
13 +class LP_Jwt_Public {
14 + private $name;
15 +
16 + private $version;
17 +
18 + private $namespace;
19 +
20 + private $jwt_error;
21 +
22 + private $secret_key;
23 +
24 + public function __construct( $name, $version ) {
25 + $this->name = $name;
26 + $this->version = $version;
27 + $this->namespace = $this->name . '/' . $this->version;
28 +
29 + if ( ! defined( 'SECURE_AUTH_KEY' ) && ! defined( 'LP_SECURE_AUTH_KEY' ) ) {
30 + return;
31 + }
32 +
33 + $this->secret_key = defined( 'LP_SECURE_AUTH_KEY' ) ? LP_SECURE_AUTH_KEY : SECURE_AUTH_KEY;
34 + }
35 +
36 + public function register_routes() {
37 + register_rest_route(
38 + $this->namespace,
39 + 'token',
40 + array(
41 + 'methods' => WP_REST_Server::CREATABLE,
42 + 'callback' => array( $this, 'generate_token' ),
43 + 'args' => array(
44 + 'username' => array(
45 + 'description' => esc_html__( 'The username of the user.', 'learnpress' ),
46 + 'type' => 'string',
47 + 'sanitize_callback' => 'sanitize_text_field',
48 + 'validate_callback' => 'rest_validate_request_arg',
49 + ),
50 + 'password' => array(
51 + 'description' => esc_html__( 'The password of the user.', 'learnpress' ),
52 + 'type' => 'string',
53 + 'sanitize_callback' => 'sanitize_text_field',
54 + 'validate_callback' => 'rest_validate_request_arg',
55 + ),
56 + ),
57 + 'schema' => array( $this, 'get_item_schema' ),
58 + 'permission_callback' => '__return_true',
59 + )
60 + );
61 +
62 + register_rest_route(
63 + $this->namespace,
64 + 'token/validate',
65 + array(
66 + 'methods' => WP_REST_Server::CREATABLE,
67 + 'callback' => array( $this, 'validate_token' ),
68 + 'permission_callback' => '__return_true',
69 + )
70 + );
71 +
72 + register_rest_route(
73 + $this->namespace,
74 + 'token/register',
75 + array(
76 + 'methods' => WP_REST_Server::CREATABLE,
77 + 'callback' => array( $this, 'register' ),
78 + 'permission_callback' => '__return_true',
79 + )
80 + );
81 + }
82 +
83 + public function get_item_schema() {
84 + $schema = array(
85 + '$schema' => 'http://json-schema.org/draft-04/schema#',
86 + 'title' => esc_html__( 'JSON Web Token', 'learnpress' ),
87 + 'type' => 'object',
88 + 'properties' => array(
89 + 'token' => array(
90 + 'description' => esc_html__( 'JSON Web Token.', 'learnpress' ),
91 + 'type' => 'string',
92 + 'readonly' => true,
93 + ),
94 + 'user_id' => array(
95 + 'description' => esc_html__( 'The ID of the user.', 'learnpress' ),
96 + 'type' => 'integer',
97 + 'readonly' => true,
98 + ),
99 + 'user_login' => array(
100 + 'description' => esc_html__( 'The username of the user', 'learnpress' ),
101 + 'type' => 'string',
102 + 'readonly' => true,
103 + ),
104 + 'user_email' => array(
105 + 'description' => esc_html__( 'The email address of the user.', 'learnpress' ),
106 + 'type' => 'string',
107 + 'readonly' => true,
108 + ),
109 + ),
110 + );
111 +
112 + return apply_filters( 'lp_rest_authentication_token_schema', $schema );
113 + }
114 +
115 + /**
116 + * Add CORs support to the request.
117 + */
118 + public function add_cors_support() {
119 + $enable_cors = defined( 'LP_JWT_AUTH_CORS_ENABLE' ) ? LP_JWT_AUTH_CORS_ENABLE : false;
120 +
121 + if ( $enable_cors ) {
122 + $headers = apply_filters( 'lp_jwt_auth_cors_allow_headers', 'Access-Control-Allow-Headers, Content-Type, Authorization' );
123 + header( sprintf( 'Access-Control-Allow-Headers: %s', $headers ) );
124 + }
125 + }
126 +
127 + public function register( WP_REST_Request $request ) {
128 + $username = $request->get_param( 'username' );
129 + $password = $request->get_param( 'password' );
130 + $confirm_password = $request->get_param( 'confirm_password' );
131 + $email = $request->get_param( 'email' );
132 +
133 + $customer_id = LP_Forms_Handler::learnpress_create_new_customer( $email, $username, $password, $confirm_password );
134 +
135 + if ( is_wp_error( $customer_id ) ) {
136 + return new WP_Error(
137 + $customer_id->get_error_code(),
138 + $customer_id->get_error_message(),
139 + array(
140 + 'status' => 403,
141 + )
142 + );
143 + }
144 +
145 + return $this->generate_token( $request );
146 + }
147 +
148 + public function generate_token( WP_REST_Request $request ) {
149 + $secret_key = $this->secret_key;
150 + $username = $request->get_param( 'username' );
151 + $password = $request->get_param( 'password' );
152 +
153 + if ( ! $secret_key ) {
154 + return new WP_Error(
155 + 'lp_jwt_auth_bad_config',
156 + esc_html__( 'LearnPress JWT is not configurated properly, please contact the admin', 'learnpress' ),
157 + array(
158 + 'status' => 403,
159 + )
160 + );
161 + }
162 +
163 + /** Try to authenticate the user with the passed credentials*/
164 + $user = wp_authenticate( $username, $password );
165 +
166 + /** If the authentication fails return a error*/
167 + if ( is_wp_error( $user ) ) {
168 + $error_code = $user->get_error_code();
169 +
170 + return new WP_Error(
171 + '[lp_jwt_auth] ' . $error_code,
172 + $user->get_error_message( $error_code ),
173 + array(
174 + 'status' => 403,
175 + )
176 + );
177 + }
178 +
179 + /** Valid credentials, the user exists create the according Token */
180 + $issued_at = time();
181 + $not_before = apply_filters( 'lp_jwt_auth_not_before', $issued_at, $issued_at );
182 + $expire = apply_filters( 'lp_jwt_auth_expire', $issued_at + WEEK_IN_SECONDS, $issued_at );
183 +
184 + $token = array(
185 + 'iss' => get_bloginfo( 'url' ),
186 + 'iat' => $issued_at,
187 + 'nbf' => $not_before,
188 + 'exp' => $expire,
189 + 'data' => array(
190 + 'user' => array(
191 + 'id' => $user->data->ID,
192 + ),
193 + ),
194 + );
195 +
196 + /** Let the user modify the token data before the sign. */
197 + $token = JWT::encode( apply_filters( 'lp_jwt_auth_token_before_sign', $token, $user ), $secret_key );
198 +
199 + /** The token is signed, now create the object with no sensible user data to the client*/
200 + $data = array(
201 + 'token' => $token,
202 + 'user_id' => $user->data->ID,
203 + 'user_login' => $user->data->user_login,
204 + 'user_email' => $user->data->user_email,
205 + 'user_display_name' => $user->data->display_name,
206 + );
207 +
208 + return apply_filters( 'lp_jwt_auth_token_before_dispatch', $data, $user );
209 + }
210 +
211 + /**
212 + * This is our Middleware to try to authenticate the user according to the
213 + * token send.
214 + *
215 + * @param (int|bool) $user Logged User ID
216 + *
217 + * @return (int|bool)
218 + */
219 + public function determine_current_user( $user_id ) {
220 + if ( ! empty( $user_id ) ) {
221 + return $user_id;
222 + }
223 +
224 + $rest_prefix = trailingslashit( rest_get_url_prefix() );
225 + $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) );
226 +
227 + /**
228 + * Only process REST requests.
229 + */
230 + if ( strpos( $request_uri, $rest_prefix ) === false ) {
231 + return $user_id;
232 + }
233 +
234 + /*
235 + * Skip the token endpoint itself to avoid double validation.
236 + */
237 + if ( strpos( $request_uri, $rest_prefix . $this->namespace . '/token' ) !== false ) {
238 + return $user_id;
239 + }
240 +
241 + /*
242 + * No Authorization header → let other auth methods (cookie, app passwords) handle it.
243 + */
244 + $has_auth = ! empty( $_SERVER['HTTP_AUTHORIZATION'] ) || ! empty( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] );
245 + if ( ! $has_auth ) {
246 + return $user_id;
247 + }
248 +
249 + /** Public LP endpoints that should not surface auth errors. */
250 + $is_public_lp = (bool) ( strpos( $request_uri, '/courses' ) || strpos( $request_uri, '/reset-password' ) || strpos( $request_uri, '/course_category' ) || strpos( $request_uri, '/sections/' ) || strpos( $request_uri, '/section-items/' ) || strpos( $request_uri, '/users' ) );
251 +
252 + $is_lp_api = strpos( $request_uri, $rest_prefix . $this->name . '/' ) !== false;
253 +
254 + $token = $this->validate_token( false );
255 +
256 + if ( is_wp_error( $token ) ) {
257 + if ( $is_lp_api && ! $is_public_lp ) {
258 + $this->jwt_error = $token;
259 + }
260 +
261 + return $user_id;
262 + }
263 +
264 + return $token->data->user->id;
265 + }
266 +
267 + public function validate_token( $output = true ) {
268 + /*
269 + * Looking for the HTTP_AUTHORIZATION header, if not present just
270 + * return the user.
271 + */
272 + $auth = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? sanitize_text_field( $_SERVER['HTTP_AUTHORIZATION'] ) : false;
273 +
274 + /* Double check for different auth header string (server dependent) */
275 + if ( ! $auth ) {
276 + $auth = isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ? sanitize_text_field( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) : false;
277 + }
278 +
279 + if ( ! $auth ) {
280 + return new WP_Error(
281 + 'lp_jwt_auth_no_auth_header',
282 + esc_html__( 'Authorization header not found.', 'learnpress' ),
283 + array(
284 + 'status' => 401,
285 + )
286 + );
287 + }
288 +
289 + /*
290 + * The HTTP_AUTHORIZATION is present verify the format
291 + * if the format is wrong return the user.
292 + */
293 + list( $token ) = sscanf( $auth, 'Bearer %s' );
294 +
295 + if ( ! $token ) {
296 + return new WP_Error(
297 + 'lp_jwt_auth_bad_auth_header',
298 + esc_html__( 'Authentication token is missing.', 'learnpress' ),
299 + array(
300 + 'status' => 401,
301 + )
302 + );
303 + }
304 +
305 + /** Get the Secret Key */
306 + $secret_key = $this->secret_key;
307 +
308 + if ( ! $secret_key ) {
309 + return new WP_Error(
310 + 'lp_jwt_auth_bad_config',
311 + esc_html__( 'LearnPress JWT is not configurated properly, please contact the admin', 'learnpress' ),
312 + array(
313 + 'status' => 401,
314 + )
315 + );
316 + }
317 +
318 + /** Try to decode the token */
319 + try {
320 + $token = JWT::decode( $token, $secret_key, array( 'HS256' ) );
321 +
322 + /** The Token is decoded now validate the iss */
323 + if ( $token->iss != get_bloginfo( 'url' ) ) {
324 + return new WP_Error(
325 + 'lp_jwt_auth_bad_iss',
326 + esc_html__( 'The iss do not match with this server', 'learnpress' ),
327 + array(
328 + 'status' => 401,
329 + )
330 + );
331 + }
332 +
333 + /** So far so good, validate the user id in the token */
334 + if ( ! isset( $token->data->user->id ) ) {
335 + return new WP_Error(
336 + 'lp_jwt_auth_bad_request',
337 + esc_html__( 'User ID not found in the token', 'learnpress' ),
338 + array(
339 + 'status' => 401,
340 + )
341 + );
342 + }
343 +
344 + if ( ! isset( $token->exp ) ) {
345 + return new WP_Error(
346 + 'rest_authentication_missing_token_expiration',
347 + esc_html__( 'The token must have an expiration date.', 'learnpress' ),
348 + array(
349 + 'status' => 401,
350 + )
351 + );
352 + }
353 +
354 + if ( time() > $token->exp ) {
355 + return new WP_Error(
356 + 'rest_authentication_token_expired',
357 + esc_html__( 'The token has expired.', 'learnpress' ),
358 + array(
359 + 'status' => 401,
360 + )
361 + );
362 + }
363 +
364 + /** Everything looks good return the decoded token if the $output is false */
365 + if ( ! $output ) {
366 + return $token;
367 + }
368 +
369 + /** If the output is true return an answer to the request to show it */
370 + return array(
371 + 'code' => 'lp_jwt_auth_valid_token',
372 + 'message' => esc_html__( 'Valid access token.', 'learnpress' ),
373 + 'data' => array(
374 + 'status' => 200,
375 + 'exp' => $token->exp - time(),
376 + ),
377 + );
378 + } catch ( Exception $e ) {
379 + return new WP_Error(
380 + 'lp_jwt_auth_invalid_token',
381 + $e->getMessage(),
382 + array(
383 + 'status' => 401,
384 + )
385 + );
386 + }
387 + }
388 +
389 + /**
390 + * Filter to hook the rest_pre_dispatch, if the is an error in the request
391 + * send it, if there is no error just continue with the current request.
392 + *
393 + * @param $request
394 + */
395 + public function rest_pre_dispatch( $request ) {
396 + if ( is_wp_error( $this->jwt_error ) ) {
397 + return $this->jwt_error;
398 + }
399 +
400 + return $request;
401 + }
402 +}