Completed
Push — add/e2e-connection-purchase-fl... ( d02cce...68beb5 )
by Yaroslav
14:07 queued 04:35
created

Rest_Authentication   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 148
rs 10
c 0
b 0
f 0
wmc 21
lcom 2
cbo 3

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A init() 0 10 2
C wp_rest_authenticate() 0 69 15
A wp_rest_authentication_errors() 0 6 2
A reset_saved_auth_state() 0 4 1
1
<?php
2
/**
3
 * The Jetpack Connection Rest Authentication file.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection;
9
10
/**
11
 * The Jetpack Connection Rest Authentication class.
12
 */
13
class Rest_Authentication {
14
15
	/**
16
	 * The rest authentication status.
17
	 *
18
	 * @since 8.9.0
19
	 * @var boolean
20
	 */
21
	private $rest_authentication_status = null;
22
23
	/**
24
	 * The Manager object.
25
	 *
26
	 * @since 8.9.0
27
	 * @var Object
28
	 */
29
	private $connection_manager = null;
30
31
	/**
32
	 * Holds the singleton instance of this class
33
	 *
34
	 * @since 8.9.0
35
	 * @var Object
36
	 */
37
	private static $instance = false;
38
39
	/**
40
	 * The constructor.
41
	 */
42
	private function __construct() {
43
		$this->connection_manager = new Manager();
44
	}
45
46
	/**
47
	 * Controls the single instance of this class.
48
	 *
49
	 * @static
50
	 */
51
	public static function init() {
52
		if ( ! self::$instance ) {
53
			self::$instance = new self();
54
55
			add_filter( 'determine_current_user', array( self::$instance, 'wp_rest_authenticate' ) );
56
			add_filter( 'rest_authentication_errors', array( self::$instance, 'wp_rest_authentication_errors' ) );
57
		}
58
59
		return self::$instance;
60
	}
61
62
	/**
63
	 * Authenticates requests from Jetpack server to WP REST API endpoints.
64
	 * Uses the existing XMLRPC request signing implementation.
65
	 *
66
	 * @param int|bool $user User ID if one has been determined, false otherwise.
67
	 *
68
	 * @return int|null The user id or null if the request was not authenticated.
69
	 */
70
	public function wp_rest_authenticate( $user ) {
71
		if ( ! empty( $user ) ) {
72
			// Another authentication method is in effect.
73
			return $user;
74
		}
75
76
		Utils::init_default_constants();
77
78
		if ( ! isset( $_GET['_for'] ) || 'jetpack' !== $_GET['_for'] ) {
79
			// Nothing to do for this authentication method.
80
			return null;
81
		}
82
83
		if ( ! isset( $_GET['token'] ) && ! isset( $_GET['signature'] ) ) {
84
			// Nothing to do for this authentication method.
85
			return null;
86
		}
87
88
		if ( ! isset( $_SERVER['REQUEST_METHOD'] ) ) {
89
			$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
90
				'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
91
				__( 'The request method is missing.', 'jetpack' ),
92
				array( 'status' => 400 )
93
			);
94
			return null;
95
		}
96
97
		// Only support specific request parameters that have been tested and
98
		// are known to work with signature verification.  A different method
99
		// can be passed to the WP REST API via the '?_method=' parameter if
100
		// needed.
101
		if ( 'GET' !== $_SERVER['REQUEST_METHOD'] && 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
102
			$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
103
				'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
104
				__( 'This request method is not supported.', 'jetpack' ),
105
				array( 'status' => 400 )
106
			);
107
			return null;
108
		}
109
		if ( 'POST' !== $_SERVER['REQUEST_METHOD'] && ! empty( file_get_contents( 'php://input' ) ) ) {
110
			$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
111
				'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
112
				__( 'This request method does not support body parameters.', 'jetpack' ),
113
				array( 'status' => 400 )
114
			);
115
			return null;
116
		}
117
118
		$verified = $this->connection_manager->verify_xml_rpc_signature();
119
120
		if (
121
			$verified &&
122
			isset( $verified['type'] ) &&
123
			'user' === $verified['type'] &&
124
			! empty( $verified['user_id'] )
125
		) {
126
			// Authentication successful.
127
			$this->rest_authentication_status = true;
128
			return $verified['user_id'];
129
		}
130
131
		// Something else went wrong.  Probably a signature error.
132
		$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
133
			'rest_invalid_signature',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_signature'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
134
			__( 'The request is not signed correctly.', 'jetpack' ),
135
			array( 'status' => 400 )
136
		);
137
		return null;
138
	}
139
140
	/**
141
	 * Report authentication status to the WP REST API.
142
	 *
143
	 * @param  WP_Error|mixed $value Error from another authentication handler, null if we should handle it, or another value if not.
144
	 * @return WP_Error|boolean|null {@see WP_JSON_Server::check_authentication}
145
	 */
146
	public function wp_rest_authentication_errors( $value ) {
147
		if ( null !== $value ) {
148
			return $value;
149
		}
150
		return $this->rest_authentication_status;
151
	}
152
153
	/**
154
	 * Resets the saved authentication state in between testing requests.
155
	 */
156
	public function reset_saved_auth_state() {
157
		$this->rest_authentication_status = null;
158
		$this->connection_manager->reset_saved_auth_state();
159
	}
160
}
161