PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 All 507 releases
jetpack / jetpack_vendor / automattic / jetpack-connection / src / sso / class-helpers.php

class-helpers.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-beta, at jetpack_vendor/automattic/jetpack-connection/src/sso/class-helpers.php

400 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * A collection of helper functions used in the SSO module.
4 *
5 * @package automattic/jetpack-connection
6 */
7
8 namespace Automattic\Jetpack\Connection\SSO;
9
10 use Automattic\Jetpack\Connection\SSO;
11 use Automattic\Jetpack\Connection\Utils;
12 use Automattic\Jetpack\Constants;
13 use Jetpack_IXR_Client;
14
15 /**
16 * A collection of helper functions used in the SSO module.
17 *
18 * @since jetpack-4.1.0
19 */
20 class Helpers {
21 /**
22 * Determine if the login form should be hidden or not
23 *
24 * @return bool
25 **/
26 public static function should_hide_login_form() {
27 /**
28 * Remove the default log in form, only leave the WordPress.com log in button.
29 *
30 * @module sso
31 *
32 * @since jetpack-3.1.0
33 *
34 * @param bool get_option( 'jetpack_sso_remove_login_form', false ) Should the default log in form be removed. Default to false.
35 */
36 return (bool) apply_filters( 'jetpack_remove_login_form', get_option( 'jetpack_sso_remove_login_form', false ) );
37 }
38
39 /**
40 * Returns a boolean value for whether logging in by matching the WordPress.com user email to a
41 * Jetpack site user's email is allowed.
42 *
43 * @return bool
44 */
45 public static function match_by_email() {
46 $match_by_email = defined( 'WPCC_MATCH_BY_EMAIL' ) ? \WPCC_MATCH_BY_EMAIL : (bool) get_option( 'jetpack_sso_match_by_email', true );
47
48 /**
49 * Link the local account to an account on WordPress.com using the same email address.
50 *
51 * @module sso
52 *
53 * @since jetpack-2.6.0
54 *
55 * @param bool $match_by_email Should we link the local account to an account on WordPress.com using the same email address. Default to false.
56 */
57 return (bool) apply_filters( 'jetpack_sso_match_by_email', $match_by_email );
58 }
59
60 /**
61 * Returns a boolean for whether users are allowed to register on the Jetpack site with SSO,
62 * even though the site disallows normal registrations.
63 *
64 * @param object|null $user_data WordPress.com user information.
65 * @return bool|string
66 */
67 public static function new_user_override( $user_data = null ) {
68 $new_user_override = defined( 'WPCC_NEW_USER_OVERRIDE' ) ? \WPCC_NEW_USER_OVERRIDE : false;
69
70 /**
71 * Allow users to register on your site with a WordPress.com account, even though you disallow normal registrations.
72 * If you return a string that corresponds to a user role, the user will be given that role.
73 *
74 * @module sso
75 *
76 * @since jetpack-2.6.0
77 * @since jetpack-4.6 $user_data object is now passed to the jetpack_sso_new_user_override filter
78 *
79 * @param bool|string $new_user_override Allow users to register on your site with a WordPress.com account. Default to false.
80 * @param object|null $user_data An object containing the user data returned from WordPress.com.
81 */
82 $role = apply_filters( 'jetpack_sso_new_user_override', $new_user_override, $user_data );
83
84 if ( $role ) {
85 if ( is_string( $role ) && get_role( $role ) ) {
86 return $role;
87 } else {
88 return get_option( 'default_role' );
89 }
90 }
91
92 return false;
93 }
94
95 /**
96 * Returns a boolean value for whether two-step authentication is required for SSO.
97 *
98 * @since jetpack-4.1.0
99 *
100 * @return bool
101 */
102 public static function is_two_step_required() {
103 /**
104 * Is it required to have 2-step authentication enabled on WordPress.com to use SSO?
105 *
106 * @module sso
107 *
108 * @since jetpack-2.8.0
109 *
110 * @param bool get_option( 'jetpack_sso_require_two_step' ) Does SSO require 2-step authentication?
111 */
112 return (bool) apply_filters( 'jetpack_sso_require_two_step', get_option( 'jetpack_sso_require_two_step', false ) );
113 }
114
115 /**
116 * Returns a boolean for whether a user that is attempting to log in will be automatically
117 * redirected to WordPress.com to begin the SSO flow.
118 *
119 * @return bool
120 */
121 public static function bypass_login_forward_wpcom() {
122 /**
123 * Redirect the site's log in form to WordPress.com's log in form.
124 *
125 * @module sso
126 *
127 * @since jetpack-3.1.0
128 *
129 * @param bool false Should the site's log in form be automatically forwarded to WordPress.com's log in form.
130 */
131 return (bool) apply_filters( 'jetpack_sso_bypass_login_forward_wpcom', false );
132 }
133
134 /**
135 * Returns a boolean for whether the SSO login form should be displayed as the default
136 * when both the default and SSO login form allowed.
137 *
138 * @since jetpack-4.1.0
139 *
140 * @return bool
141 */
142 public static function show_sso_login() {
143 if ( self::should_hide_login_form() ) {
144 return true;
145 }
146
147 /**
148 * Display the SSO login form as the default when both the default and SSO login forms are enabled.
149 *
150 * @module sso
151 *
152 * @since jetpack-4.1.0
153 *
154 * @param bool true Should the SSO login form be displayed by default when the default login form is also enabled?
155 */
156 return (bool) apply_filters( 'jetpack_sso_default_to_sso_login', true );
157 }
158
159 /**
160 * Returns a boolean for whether the two step required checkbox, displayed on the Jetpack admin page, should be disabled.
161 *
162 * @since jetpack-4.1.0
163 *
164 * @return bool
165 */
166 public static function is_require_two_step_checkbox_disabled() {
167 return (bool) has_filter( 'jetpack_sso_require_two_step' );
168 }
169
170 /**
171 * Returns a boolean for whether the match by email checkbox, displayed on the Jetpack admin page, should be disabled.
172 *
173 * @since jetpack-4.1.0
174 *
175 * @return bool
176 */
177 public static function is_match_by_email_checkbox_disabled() {
178 return defined( 'WPCC_MATCH_BY_EMAIL' ) || has_filter( 'jetpack_sso_match_by_email' );
179 }
180
181 /**
182 * Returns an array of hosts that SSO will redirect to.
183 *
184 * Instead of accessing JETPACK__API_BASE within the method directly, we set it as the
185 * default for $api_base due to restrictions with testing constants in our tests.
186 *
187 * @since jetpack-4.3.0
188 * @since jetpack-4.6.0 Added public-api.wordpress.com as an allowed redirect
189 *
190 * @param array $hosts Allowed redirect hosts.
191 * @param string $api_base Base API URL.
192 *
193 * @return array
194 */
195 public static function allowed_redirect_hosts( $hosts, $api_base = '' ) {
196 if ( empty( $api_base ) ) {
197 $api_base = Constants::get_constant( 'JETPACK__API_BASE' );
198 }
199
200 if ( empty( $hosts ) ) {
201 $hosts = array();
202 }
203
204 $hosts[] = 'wordpress.com';
205 $hosts[] = 'jetpack.wordpress.com';
206 $hosts[] = 'public-api.wordpress.com';
207 $hosts[] = 'jetpack.com';
208
209 if ( ! str_contains( $api_base, 'jetpack.wordpress.com/jetpack' ) ) {
210 $base_url_parts = wp_parse_url( esc_url_raw( $api_base ) );
211 if ( $base_url_parts && ! empty( $base_url_parts['host'] ) ) {
212 $hosts[] = $base_url_parts['host'];
213 }
214 }
215
216 foreach ( array( SSO::get_broker_url(), SSO::get_broker_auth_url() ) as $broker_url ) {
217 if ( $broker_url ) {
218 $broker_parts = wp_parse_url( $broker_url );
219 if ( $broker_parts && ! empty( $broker_parts['host'] ) ) {
220 $hosts[] = $broker_parts['host'];
221 }
222 }
223 }
224
225 return array_unique( $hosts );
226 }
227
228 /**
229 * Determines how long the auth cookie is valid for when a user logs in with SSO.
230 *
231 * @return int result of the jetpack_sso_auth_cookie_expiration filter.
232 */
233 public static function extend_auth_cookie_expiration_for_sso() {
234 /**
235 * Determines how long the auth cookie is valid for when a user logs in with SSO.
236 *
237 * @module sso
238 *
239 * @since jetpack-4.4.0
240 * @since jetpack-6.1.0 Fixed a typo. Filter was previously jetpack_sso_auth_cookie_expirtation.
241 *
242 * @param int YEAR_IN_SECONDS
243 */
244 return (int) apply_filters( 'jetpack_sso_auth_cookie_expiration', YEAR_IN_SECONDS );
245 }
246
247 /**
248 * Determines if the SSO form should be displayed for the current action.
249 *
250 * @since jetpack-4.6.0
251 *
252 * @param string $action SSO action being performed.
253 *
254 * @return bool Is SSO allowed for the current action?
255 */
256 public static function display_sso_form_for_action( $action ) {
257 /**
258 * Allows plugins the ability to overwrite actions where the SSO form is allowed to be used.
259 *
260 * @module sso
261 *
262 * @since jetpack-4.6.0
263 *
264 * @param array $allowed_actions_for_sso
265 */
266 $allowed_actions_for_sso = (array) apply_filters(
267 'jetpack_sso_allowed_actions',
268 array(
269 'login',
270 'jetpack-sso',
271 'jetpack_json_api_authorization',
272 'entered_recovery_mode',
273 )
274 );
275 return in_array( $action, $allowed_actions_for_sso, true );
276 }
277
278 /**
279 * This method returns an environment array that is meant to simulate `$_REQUEST` when the initial
280 * JSON API auth request was made.
281 *
282 * @since jetpack-4.6.0
283 *
284 * @return array|bool
285 */
286 public static function get_json_api_auth_environment() {
287 if ( empty( $_COOKIE['jetpack_sso_original_request'] ) ) {
288 return false;
289 }
290
291 $original_request = esc_url_raw( wp_unslash( $_COOKIE['jetpack_sso_original_request'] ) );
292
293 $parsed_url = wp_parse_url( $original_request );
294 if ( empty( $parsed_url ) || empty( $parsed_url['query'] ) ) {
295 return false;
296 }
297
298 $args = array();
299 wp_parse_str( $parsed_url['query'], $args );
300
301 if ( empty( $args ) || empty( $args['action'] ) ) {
302 return false;
303 }
304
305 if ( 'jetpack_json_api_authorization' !== $args['action'] ) {
306 return false;
307 }
308
309 return array_merge(
310 $args,
311 array( 'jetpack_json_api_original_query' => $original_request )
312 );
313 }
314
315 /**
316 * Check if the site has a custom login page URL, and return it.
317 * If default login page URL is used (`wp-login.php`), `null` will be returned.
318 *
319 * @return string|null
320 */
321 public static function get_custom_login_url() {
322 $login_url = wp_login_url();
323
324 if ( str_ends_with( $login_url, 'wp-login.php' ) ) {
325 // No custom URL found.
326 return null;
327 }
328
329 $site_url = trailingslashit( site_url() );
330
331 if ( ! str_starts_with( $login_url, $site_url ) ) {
332 // Something went wrong, we can't properly extract the custom URL.
333 return null;
334 }
335
336 // Extracting the "path" part of the URL, because we don't need the `site_url` part.
337 return str_ireplace( $site_url, '', $login_url );
338 }
339
340 /**
341 * Clear the cookies that store the profile information for the last
342 * WPCOM user to connect.
343 */
344 public static function clear_wpcom_profile_cookies() {
345 if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_name_' . COOKIEHASH ] ) ) {
346 setcookie(
347 'jetpack_sso_wpcom_name_' . COOKIEHASH,
348 ' ',
349 time() - YEAR_IN_SECONDS,
350 COOKIEPATH,
351 COOKIE_DOMAIN,
352 is_ssl(),
353 true
354 );
355 }
356
357 if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH ] ) ) {
358 setcookie(
359 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH,
360 ' ',
361 time() - YEAR_IN_SECONDS,
362 COOKIEPATH,
363 COOKIE_DOMAIN,
364 is_ssl(),
365 true
366 );
367 }
368 }
369
370 /**
371 * Remove an SSO connection for a user.
372 *
373 * @param int $user_id The local user id.
374 */
375 public static function delete_connection_for_user( $user_id ) {
376 $wpcom_user_id = Utils::get_wpcom_user_id( $user_id );
377 if ( ! $wpcom_user_id ) {
378 return;
379 }
380
381 $xml = new Jetpack_IXR_Client(
382 array(
383 'wpcom_user_id' => $user_id,
384 )
385 );
386 $xml->query( 'jetpack.sso.removeUser', $wpcom_user_id );
387
388 if ( $xml->isError() ) {
389 return false;
390 }
391
392 // Clean up local data stored for SSO.
393 Utils::delete_wpcom_user_id( $user_id );
394 delete_user_meta( $user_id, 'wpcom_user_data' );
395 self::clear_wpcom_profile_cookies();
396
397 return $xml->getResponse();
398 }
399 }
400