PluginProbe
Manage – Centralized site maintenance and monitoring / trunk
Manage – Centralized site maintenance and monitoring vtrunk
1.0.9 1.0.8 1.0.7 1.0.6 1.0.5 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4
manage / modules / api / classes / route.php

route.php in Manage – Centralized site maintenance and monitoring trunk, at modules/api/classes/route.php

119 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Manage\Modules\Api\Classes;
3
4 use Manage\Classes\Manage_Client;
5 use Manage\Classes\Jwks_Decoder;
6 use Manage\Classes\System_User;
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 abstract class Route {
13
14 const NAMESPACE = 'manage/v1';
15
16 abstract public function register_routes();
17
18 public function __construct() {
19 add_action( 'rest_api_init', [ $this, 'register_routes' ] );
20 }
21
22 public function token_authentication( $request ) {
23 if ( $this->is_authentication_skipped() ) {
24 return true;
25 }
26
27 $auth_header = $this->get_authorization_header( $request );
28
29 if ( ! $auth_header ) {
30 return new \WP_Error( 'no_auth_header', 'Authorization header missing.', [ 'status' => \WP_Http::UNAUTHORIZED ] );
31 }
32
33 if ( ! preg_match( '/Bearer\s(\S+)/', $auth_header, $matches ) ) {
34 return new \WP_Error( 'invalid_token', 'Invalid or missing token.', [ 'status' => \WP_Http::FORBIDDEN ] );
35 }
36
37 $token = $matches[1];
38
39 $jwt_payload = Jwks_Decoder::decode( $token );
40 if ( is_wp_error( $jwt_payload ) ) {
41 return new \WP_Error( $jwt_payload->get_error_code(), $jwt_payload->get_error_message(), [ 'status' => \WP_Http::FORBIDDEN ] );
42 }
43
44 if ( empty( $jwt_payload['sub'] ) || Manage_Client::get_client_id() !== $jwt_payload['sub'] ) {
45 return new \WP_Error( 'invalid_site_id', 'Invalid site ID in token.', [ 'status' => \WP_Http::FORBIDDEN ] );
46 }
47
48 $system_user = System_User::get_system_user();
49
50 if ( ! $system_user ) {
51 return new \WP_Error( 'system_user_not_exists', 'System user does not exist.', [ 'status' => \WP_Http::FORBIDDEN ] );
52 }
53
54 $user_status = System_User::get_user_status( $system_user );
55
56 if ( System_User::STATUS_USER_NO_PERMISSIONS === $user_status ) {
57 return new \WP_Error( 'system_user_no_permissions', 'System user does not have admin permissions.', [ 'status' => \WP_Http::FORBIDDEN ] );
58 }
59
60 wp_set_current_user( $system_user->ID );
61
62 return true;
63 }
64
65 private function get_authorization_header( \WP_REST_Request $request ): string {
66 /*
67 * Some hosts/proxies (CDN/WAF, FastCGI, mod_security) strip the standard
68 * Authorization header before it reaches PHP. eis-manage sends the same
69 * Bearer token under X-Manage-Authorization as a fallback. Standard
70 * Authorization is preferred when both are present.
71 */
72 foreach ( [ 'authorization', 'x-manage-authorization' ] as $header_name ) {
73 $value = $request->get_header( $header_name );
74
75 if ( $value ) {
76 return $value;
77 }
78 }
79
80 /*
81 * WP_REST_Server::get_headers() already handles HTTP_AUTHORIZATION and
82 * REDIRECT_HTTP_AUTHORIZATION, but getallheaders() can still surface the
83 * header on servers where neither $_SERVER key is populated.
84 */
85 if ( function_exists( 'getallheaders' ) ) {
86 foreach ( getallheaders() as $name => $value ) {
87 if (
88 strcasecmp( $name, 'authorization' ) === 0 ||
89 strcasecmp( $name, 'x-manage-authorization' ) === 0
90 ) {
91 return sanitize_text_field( $value );
92 }
93 }
94 }
95
96 return '';
97 }
98
99 private function is_authentication_skipped(): bool {
100 if ( ! defined( 'MANAGE_DEV_MODE' ) || ! MANAGE_DEV_MODE ) {
101 return false;
102 }
103
104 if ( ! $this->is_local_ip() ) {
105 return false;
106 }
107
108 return true;
109 }
110
111 private function is_local_ip(): bool {
112 if ( ! empty( $_SERVER['REMOTE_ADDR'] ) && in_array( $_SERVER['REMOTE_ADDR'], [ '127.0.0.1', '::1' ], true ) ) {
113 return true;
114 }
115
116 return false;
117 }
118 }
119