Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | require_once( JETPACK__PLUGIN_DIR . 'modules/sso/class.jetpack-sso-helpers.php' ); |
||
| 3 | require_once( JETPACK__PLUGIN_DIR . 'modules/sso/class.jetpack-sso-notices.php' ); |
||
| 4 | |||
| 5 | /** |
||
| 6 | * Module Name: Single Sign On |
||
| 7 | * Module Description: Secure user authentication with WordPress.com. |
||
| 8 | * Jumpstart Description: Lets you log in to all your Jetpack-enabled sites with one click using your WordPress.com account. |
||
| 9 | * Sort Order: 30 |
||
| 10 | * Recommendation Order: 5 |
||
| 11 | * First Introduced: 2.6 |
||
| 12 | * Requires Connection: Yes |
||
| 13 | * Auto Activate: No |
||
| 14 | * Module Tags: Developers |
||
| 15 | * Feature: Security, Jumpstart |
||
| 16 | * Additional Search Queries: sso, single sign on, login, log in |
||
| 17 | */ |
||
| 18 | |||
| 19 | class Jetpack_SSO { |
||
| 20 | static $instance = null; |
||
| 21 | |||
| 22 | private function __construct() { |
||
| 23 | |||
| 24 | self::$instance = $this; |
||
| 25 | |||
| 26 | add_action( 'admin_init', array( $this, 'maybe_authorize_user_after_sso' ), 1 ); |
||
| 27 | add_action( 'admin_init', array( $this, 'register_settings' ) ); |
||
| 28 | add_action( 'login_init', array( $this, 'login_init' ) ); |
||
| 29 | add_action( 'delete_user', array( $this, 'delete_connection_for_user' ) ); |
||
| 30 | add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) ); |
||
| 31 | add_action( 'init', array( $this, 'maybe_logout_user' ), 5 ); |
||
| 32 | add_action( 'jetpack_modules_loaded', array( $this, 'module_configure_button' ) ); |
||
| 33 | add_action( 'login_form_logout', array( $this, 'store_wpcom_profile_cookies_on_logout' ) ); |
||
| 34 | add_action( 'wp_login', array( 'Jetpack_SSO', 'clear_wpcom_profile_cookies' ) ); |
||
| 35 | add_action( 'jetpack_unlinked_user', array( $this, 'delete_connection_for_user') ); |
||
| 36 | |||
| 37 | // Adding this action so that on login_init, the action won't be sanitized out of the $action global. |
||
| 38 | add_action( 'login_form_jetpack-sso', '__return_true' ); |
||
| 39 | } |
||
| 40 | |||
| 41 | /** |
||
| 42 | * Returns the single instance of the Jetpack_SSO object |
||
| 43 | * |
||
| 44 | * @since 2.8 |
||
| 45 | * @return Jetpack_SSO |
||
| 46 | **/ |
||
| 47 | public static function get_instance() { |
||
| 48 | if ( ! is_null( self::$instance ) ) { |
||
| 49 | return self::$instance; |
||
| 50 | } |
||
| 51 | |||
| 52 | return self::$instance = new Jetpack_SSO; |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * Add configure button and functionality to the module card on the Jetpack screen |
||
| 57 | **/ |
||
| 58 | public static function module_configure_button() { |
||
| 59 | Jetpack::enable_module_configurable( __FILE__ ); |
||
| 60 | Jetpack::module_configuration_load( __FILE__, array( __CLASS__, 'module_configuration_load' ) ); |
||
| 61 | Jetpack::module_configuration_head( __FILE__, array( __CLASS__, 'module_configuration_head' ) ); |
||
| 62 | Jetpack::module_configuration_screen( __FILE__, array( __CLASS__, 'module_configuration_screen' ) ); |
||
| 63 | } |
||
| 64 | |||
| 65 | public static function module_configuration_load() {} |
||
| 66 | |||
| 67 | public static function module_configuration_head() {} |
||
| 68 | |||
| 69 | public static function module_configuration_screen() { |
||
| 70 | ?> |
||
| 71 | <form method="post" action="options.php"> |
||
| 72 | <?php settings_fields( 'jetpack-sso' ); ?> |
||
| 73 | <?php do_settings_sections( 'jetpack-sso' ); ?> |
||
| 74 | <?php submit_button(); ?> |
||
| 75 | </form> |
||
| 76 | <?php |
||
| 77 | } |
||
| 78 | |||
| 79 | /** |
||
| 80 | * If jetpack_force_logout == 1 in current user meta the user will be forced |
||
| 81 | * to logout and reauthenticate with the site. |
||
| 82 | **/ |
||
| 83 | public function maybe_logout_user() { |
||
| 84 | global $current_user; |
||
| 85 | |||
| 86 | if ( 1 == $current_user->jetpack_force_logout ) { |
||
| 87 | delete_user_meta( $current_user->ID, 'jetpack_force_logout' ); |
||
| 88 | self::delete_connection_for_user( $current_user->ID ); |
||
| 89 | wp_logout(); |
||
| 90 | wp_safe_redirect( wp_login_url() ); |
||
| 91 | exit; |
||
| 92 | } |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Adds additional methods the WordPress xmlrpc API for handling SSO specific features |
||
| 97 | * |
||
| 98 | * @param array $methods |
||
| 99 | * @return array |
||
| 100 | **/ |
||
| 101 | public function xmlrpc_methods( $methods ) { |
||
| 102 | $methods['jetpack.userDisconnect'] = array( $this, 'xmlrpc_user_disconnect' ); |
||
| 103 | return $methods; |
||
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Marks a user's profile for disconnect from WordPress.com and forces a logout |
||
| 108 | * the next time the user visits the site. |
||
| 109 | **/ |
||
| 110 | public function xmlrpc_user_disconnect( $user_id ) { |
||
| 111 | $user_query = new WP_User_Query( |
||
| 112 | array( |
||
| 113 | 'meta_key' => 'wpcom_user_id', |
||
| 114 | 'meta_value' => $user_id, |
||
| 115 | ) |
||
| 116 | ); |
||
| 117 | $user = $user_query->get_results(); |
||
| 118 | $user = $user[0]; |
||
| 119 | |||
| 120 | if ( $user instanceof WP_User ) { |
||
| 121 | $user = wp_set_current_user( $user->ID ); |
||
| 122 | update_user_meta( $user->ID, 'jetpack_force_logout', '1' ); |
||
| 123 | self::delete_connection_for_user( $user->ID ); |
||
| 124 | return true; |
||
| 125 | } |
||
| 126 | return false; |
||
| 127 | } |
||
| 128 | |||
| 129 | /** |
||
| 130 | * Enqueues scripts and styles necessary for SSO login. |
||
| 131 | */ |
||
| 132 | public function login_enqueue_scripts() { |
||
| 133 | global $action; |
||
| 134 | |||
| 135 | if ( ! in_array( $action, array( 'jetpack-sso', 'login' ) ) ) { |
||
| 136 | return; |
||
| 137 | } |
||
| 138 | |||
| 139 | if ( is_rtl() ) { |
||
| 140 | wp_enqueue_style( 'jetpack-sso-login', plugins_url( 'modules/sso/jetpack-sso-login-rtl.css', JETPACK__PLUGIN_FILE ), array( 'login', 'genericons' ), JETPACK__VERSION ); |
||
| 141 | } else { |
||
| 142 | wp_enqueue_style( 'jetpack-sso-login', plugins_url( 'modules/sso/jetpack-sso-login.css', JETPACK__PLUGIN_FILE ), array( 'login', 'genericons' ), JETPACK__VERSION ); |
||
| 143 | } |
||
| 144 | |||
| 145 | wp_enqueue_script( 'jetpack-sso-login', plugins_url( 'modules/sso/jetpack-sso-login.js', JETPACK__PLUGIN_FILE ), array( 'jquery' ), JETPACK__VERSION ); |
||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Adds Jetpack SSO classes to login body |
||
| 150 | * |
||
| 151 | * @param array $classes Array of classes to add to body tag |
||
| 152 | * @return array Array of classes to add to body tag |
||
| 153 | */ |
||
| 154 | public function login_body_class( $classes ) { |
||
| 155 | global $action; |
||
| 156 | |||
| 157 | if ( ! in_array( $action, array( 'jetpack-sso', 'login' ) ) ) { |
||
| 158 | return $classes; |
||
| 159 | } |
||
| 160 | |||
| 161 | // Always add the jetpack-sso class so that we can add SSO specific styling even when the SSO form isn't being displayed. |
||
| 162 | $classes[] = 'jetpack-sso'; |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Should we show the SSO login form? |
||
| 166 | * |
||
| 167 | * $_GET['jetpack-sso-default-form'] is used to provide a fallback in case JavaScript is not enabled. |
||
| 168 | * |
||
| 169 | * The default_to_sso_login() method allows us to dynamically decide whether we show the SSO login form or not. |
||
| 170 | * The SSO module uses the method to display the default login form if we can not find a user to log in via SSO. |
||
| 171 | * But, the method could be filtered by a site admin to always show the default login form if that is preferred. |
||
| 172 | */ |
||
| 173 | if ( empty( $_GET['jetpack-sso-show-default-form'] ) && Jetpack_SSO_Helpers::show_sso_login() ) { |
||
| 174 | $classes[] = 'jetpack-sso-form-display'; |
||
| 175 | } |
||
| 176 | |||
| 177 | return $classes; |
||
| 178 | } |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Adds settings fields to Settings > General > Single Sign On that allows users to |
||
| 182 | * turn off the login form on wp-login.php |
||
| 183 | * |
||
| 184 | * @since 2.7 |
||
| 185 | **/ |
||
| 186 | public function register_settings() { |
||
| 187 | |||
| 188 | add_settings_section( |
||
| 189 | 'jetpack_sso_settings', |
||
| 190 | __( 'Single Sign On' , 'jetpack' ), |
||
| 191 | '__return_false', |
||
| 192 | 'jetpack-sso' |
||
| 193 | ); |
||
| 194 | |||
| 195 | /* |
||
| 196 | * Settings > General > Single Sign On |
||
| 197 | * Require two step authentication |
||
| 198 | */ |
||
| 199 | register_setting( |
||
| 200 | 'jetpack-sso', |
||
| 201 | 'jetpack_sso_require_two_step', |
||
| 202 | array( $this, 'validate_jetpack_sso_require_two_step' ) |
||
| 203 | ); |
||
| 204 | |||
| 205 | add_settings_field( |
||
| 206 | 'jetpack_sso_require_two_step', |
||
| 207 | '', // __( 'Require Two-Step Authentication' , 'jetpack' ), |
||
| 208 | array( $this, 'render_require_two_step' ), |
||
| 209 | 'jetpack-sso', |
||
| 210 | 'jetpack_sso_settings' |
||
| 211 | ); |
||
| 212 | |||
| 213 | /* |
||
| 214 | * Settings > General > Single Sign On |
||
| 215 | */ |
||
| 216 | register_setting( |
||
| 217 | 'jetpack-sso', |
||
| 218 | 'jetpack_sso_match_by_email', |
||
| 219 | array( $this, 'validate_jetpack_sso_match_by_email' ) |
||
| 220 | ); |
||
| 221 | |||
| 222 | add_settings_field( |
||
| 223 | 'jetpack_sso_match_by_email', |
||
| 224 | '', // __( 'Match by Email' , 'jetpack' ), |
||
| 225 | array( $this, 'render_match_by_email' ), |
||
| 226 | 'jetpack-sso', |
||
| 227 | 'jetpack_sso_settings' |
||
| 228 | ); |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * Builds the display for the checkbox allowing user to require two step |
||
| 233 | * auth be enabled on WordPress.com accounts before login. Displays in Settings > General |
||
| 234 | * |
||
| 235 | * @since 2.7 |
||
| 236 | **/ |
||
| 237 | public function render_require_two_step() { |
||
| 238 | ?> |
||
| 239 | <label> |
||
| 240 | <input |
||
| 241 | type="checkbox" |
||
| 242 | name="jetpack_sso_require_two_step" |
||
| 243 | <?php checked( Jetpack_SSO_Helpers::is_two_step_required() ); ?> |
||
| 244 | <?php disabled( Jetpack_SSO_Helpers::is_require_two_step_checkbox_disabled() ); ?> |
||
| 245 | > |
||
| 246 | <?php esc_html_e( 'Require Two-Step Authentication' , 'jetpack' ); ?> |
||
| 247 | </label> |
||
| 248 | <?php |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * Validate the require two step checkbox in Settings > General |
||
| 253 | * |
||
| 254 | * @since 2.7 |
||
| 255 | * @return boolean |
||
| 256 | **/ |
||
| 257 | public function validate_jetpack_sso_require_two_step( $input ) { |
||
| 258 | return ( ! empty( $input ) ) ? 1 : 0; |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Builds the display for the checkbox allowing the user to allow matching logins by email |
||
| 263 | * Displays in Settings > General |
||
| 264 | * |
||
| 265 | * @since 2.9 |
||
| 266 | **/ |
||
| 267 | public function render_match_by_email() { |
||
| 268 | ?> |
||
| 269 | <label> |
||
| 270 | <input |
||
| 271 | type="checkbox" |
||
| 272 | name="jetpack_sso_match_by_email" |
||
| 273 | <?php checked( Jetpack_SSO_Helpers::match_by_email() ); ?> |
||
| 274 | <?php disabled( Jetpack_SSO_Helpers::is_match_by_email_checkbox_disabled() ); ?> |
||
| 275 | > |
||
| 276 | <?php esc_html_e( 'Match by Email', 'jetpack' ); ?> |
||
| 277 | </label> |
||
| 278 | <?php |
||
| 279 | } |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Validate the match by email check in Settings > General |
||
| 283 | * |
||
| 284 | * @since 2.9 |
||
| 285 | * @return boolean |
||
| 286 | **/ |
||
| 287 | public function validate_jetpack_sso_match_by_email( $input ) { |
||
| 288 | return ( ! empty( $input ) ) ? 1 : 0; |
||
| 289 | } |
||
| 290 | |||
| 291 | /** |
||
| 292 | * Checks to determine if the user wants to login on wp-login |
||
| 293 | * |
||
| 294 | * This function mostly exists to cover the exceptions to login |
||
| 295 | * that may exist as other parameters to $_GET[action] as $_GET[action] |
||
| 296 | * does not have to exist. By default WordPress assumes login if an action |
||
| 297 | * is not set, however this may not be true, as in the case of logout |
||
| 298 | * where $_GET[loggedout] is instead set |
||
| 299 | * |
||
| 300 | * @return boolean |
||
| 301 | **/ |
||
| 302 | private function wants_to_login() { |
||
| 303 | $wants_to_login = false; |
||
| 304 | |||
| 305 | // Cover default WordPress behavior |
||
| 306 | $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login'; |
||
| 307 | |||
| 308 | // And now the exceptions |
||
| 309 | $action = isset( $_GET['loggedout'] ) ? 'loggedout' : $action; |
||
| 310 | |||
| 311 | if ( 'login' == $action ) { |
||
| 312 | $wants_to_login = true; |
||
| 313 | } |
||
| 314 | |||
| 315 | return $wants_to_login; |
||
| 316 | } |
||
| 317 | |||
| 318 | function login_init() { |
||
| 319 | global $action; |
||
| 320 | |||
| 321 | if ( Jetpack_SSO_Helpers::should_hide_login_form() ) { |
||
| 322 | /** |
||
| 323 | * Since the default authenticate filters fire at priority 20 for checking username and password, |
||
| 324 | * let's fire at priority 30. wp_authenticate_spam_check is fired at priority 99, but since we return a |
||
| 325 | * WP_Error in disable_default_login_form, then we won't trigger spam processing logic. |
||
| 326 | */ |
||
| 327 | add_filter( 'authenticate', array( 'Jetpack_SSO_Notices', 'disable_default_login_form' ), 30 ); |
||
| 328 | |||
| 329 | /** |
||
| 330 | * Filter the display of the disclaimer message appearing when default WordPress login form is disabled. |
||
| 331 | * |
||
| 332 | * @module sso |
||
| 333 | * |
||
| 334 | * @since 2.8.0 |
||
| 335 | * |
||
| 336 | * @param bool true Should the disclaimer be displayed. Default to true. |
||
| 337 | */ |
||
| 338 | $display_sso_disclaimer = apply_filters( 'jetpack_sso_display_disclaimer', true ); |
||
| 339 | if ( $display_sso_disclaimer ) { |
||
| 340 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'msg_login_by_jetpack' ) ); |
||
| 341 | } |
||
| 342 | } |
||
| 343 | |||
| 344 | /** |
||
| 345 | * If the user is attempting to logout AND the auto-forward to WordPress.com |
||
| 346 | * login is set then we need to ensure we do not auto-forward the user and get |
||
| 347 | * them stuck in an infinite logout loop. |
||
| 348 | */ |
||
| 349 | if ( isset( $_GET['loggedout'] ) && Jetpack_SSO_Helpers::bypass_login_forward_wpcom() ) { |
||
| 350 | add_filter( 'jetpack_remove_login_form', '__return_true' ); |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * Check to see if the site admin wants to automagically forward the user |
||
| 355 | * to the WordPress.com login page AND that the request to wp-login.php |
||
| 356 | * is not something other than login (Like logout!) |
||
| 357 | */ |
||
| 358 | View Code Duplication | if ( |
|
| 359 | $this->wants_to_login() |
||
| 360 | && Jetpack_SSO_Helpers::bypass_login_forward_wpcom() |
||
| 361 | ) { |
||
| 362 | add_filter( 'allowed_redirect_hosts', array( 'Jetpack_SSO_Helpers', 'allowed_redirect_hosts' ) ); |
||
| 363 | $this->maybe_save_cookie_redirect(); |
||
| 364 | $reauth = ! empty( $_GET['force_reauth'] ); |
||
| 365 | $sso_url = $this->get_sso_url_or_die( $reauth ); |
||
| 366 | JetpackTracking::record_user_event( 'sso_login_redirect_bypass_success' ); |
||
| 367 | wp_safe_redirect( $sso_url ); |
||
| 368 | exit; |
||
|
0 ignored issues
–
show
|
|||
| 369 | } |
||
| 370 | |||
| 371 | if ( 'login' === $action ) { |
||
| 372 | $this->display_sso_login_form(); |
||
| 373 | } elseif ( 'jetpack-sso' === $action ) { |
||
| 374 | if ( isset( $_GET['result'], $_GET['user_id'], $_GET['sso_nonce'] ) && 'success' == $_GET['result'] ) { |
||
| 375 | $this->handle_login(); |
||
| 376 | $this->display_sso_login_form(); |
||
| 377 | } else { |
||
| 378 | if ( Jetpack::check_identity_crisis() ) { |
||
| 379 | JetpackTracking::record_user_event( 'sso_login_redirect_failed', array( |
||
| 380 | 'error_message' => 'identity_crisis' |
||
| 381 | ) ); |
||
| 382 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_msg_identity_crisis' ) ); |
||
| 383 | View Code Duplication | } else { |
|
| 384 | $this->maybe_save_cookie_redirect(); |
||
| 385 | // Is it wiser to just use wp_redirect than do this runaround to wp_safe_redirect? |
||
| 386 | add_filter( 'allowed_redirect_hosts', array( 'Jetpack_SSO_Helpers', 'allowed_redirect_hosts' ) ); |
||
| 387 | $reauth = ! empty( $_GET['force_reauth'] ); |
||
| 388 | $sso_url = $this->get_sso_url_or_die( $reauth ); |
||
| 389 | JetpackTracking::record_user_event( 'sso_login_redirect_success' ); |
||
| 390 | wp_safe_redirect( $sso_url ); |
||
| 391 | exit; |
||
|
0 ignored issues
–
show
The method
login_init() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an Loading history...
|
|||
| 392 | } |
||
| 393 | } |
||
| 394 | } |
||
| 395 | } |
||
| 396 | |||
| 397 | /** |
||
| 398 | * Ensures that we can get a nonce from WordPress.com via XML-RPC before setting |
||
| 399 | * up the hooks required to display the SSO form. |
||
| 400 | */ |
||
| 401 | public function display_sso_login_form() { |
||
| 402 | if ( Jetpack::check_identity_crisis() ) { |
||
| 403 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_msg_identity_crisis' ) ); |
||
| 404 | return; |
||
| 405 | } |
||
| 406 | |||
| 407 | $sso_nonce = self::request_initial_nonce(); |
||
| 408 | if ( is_wp_error( $sso_nonce ) ) { |
||
| 409 | return; |
||
| 410 | } |
||
| 411 | |||
| 412 | add_action( 'login_form', array( $this, 'login_form' ) ); |
||
| 413 | add_filter( 'login_body_class', array( $this, 'login_body_class' ) ); |
||
| 414 | add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts' ) ); |
||
| 415 | } |
||
| 416 | |||
| 417 | /** |
||
| 418 | * Conditionally save the redirect_to url as a cookie. |
||
| 419 | */ |
||
| 420 | public static function maybe_save_cookie_redirect() { |
||
| 421 | if ( headers_sent() ) { |
||
| 422 | return new WP_Error( 'headers_sent', __( 'Cannot deal with cookie redirects, as headers are already sent.', 'jetpack' ) ); |
||
| 423 | } |
||
| 424 | |||
| 425 | if ( ! empty( $_GET['redirect_to'] ) ) { |
||
| 426 | // If we have something to redirect to |
||
| 427 | $url = esc_url_raw( $_GET['redirect_to'] ); |
||
| 428 | setcookie( 'jetpack_sso_redirect_to', $url, time() + HOUR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, false, true ); |
||
| 429 | |||
| 430 | } elseif ( ! empty( $_COOKIE['jetpack_sso_redirect_to'] ) ) { |
||
| 431 | // Otherwise, if it's already set, purge it. |
||
| 432 | setcookie( 'jetpack_sso_redirect_to', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 433 | } |
||
| 434 | } |
||
| 435 | |||
| 436 | /** |
||
| 437 | * Outputs the Jetpack SSO button and description as well as the toggle link |
||
| 438 | * for switching between Jetpack SSO and default login. |
||
| 439 | */ |
||
| 440 | function login_form() { |
||
| 441 | $site_name = get_bloginfo( 'name' ); |
||
| 442 | if ( ! $site_name ) { |
||
| 443 | $site_name = get_bloginfo( 'url' ); |
||
| 444 | } |
||
| 445 | |||
| 446 | $display_name = ! empty( $_COOKIE[ 'jetpack_sso_wpcom_name_' . COOKIEHASH ] ) |
||
| 447 | ? $_COOKIE[ 'jetpack_sso_wpcom_name_' . COOKIEHASH ] |
||
| 448 | : false; |
||
| 449 | $gravatar = ! empty( $_COOKIE[ 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH ] ) |
||
| 450 | ? $_COOKIE[ 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH ] |
||
| 451 | : false; |
||
| 452 | |||
| 453 | ?> |
||
| 454 | <div id="jetpack-sso-wrap"> |
||
| 455 | <?php if ( $display_name && $gravatar ) : ?> |
||
| 456 | <div id="jetpack-sso-wrap__user"> |
||
| 457 | <img width="72" height="72" src="<?php echo esc_html( $gravatar ); ?>" /> |
||
| 458 | |||
| 459 | <h2> |
||
| 460 | <?php |
||
| 461 | echo wp_kses( |
||
| 462 | sprintf( __( 'Log in as <span>%s</span>', 'jetpack' ), esc_html( $display_name ) ), |
||
| 463 | array( 'span' => true ) |
||
| 464 | ); |
||
| 465 | ?> |
||
| 466 | </h2> |
||
| 467 | </div> |
||
| 468 | |||
| 469 | <?php endif; ?> |
||
| 470 | |||
| 471 | |||
| 472 | <div id="jetpack-sso-wrap__action"> |
||
| 473 | <?php echo $this->build_sso_button( array(), 'is_primary' ); ?> |
||
| 474 | |||
| 475 | <?php if ( $display_name && $gravatar ) : ?> |
||
| 476 | <a rel="nofollow" class="jetpack-sso-wrap__reauth" href="<?php echo esc_url( $this->build_sso_button_url( array( 'force_reauth' => '1' ) ) ); ?>"> |
||
| 477 | <?php esc_html_e( 'Log in as a different WordPress.com user', 'jetpack' ); ?> |
||
| 478 | </a> |
||
| 479 | <?php else : ?> |
||
| 480 | <p> |
||
| 481 | <?php |
||
| 482 | echo esc_html( |
||
| 483 | sprintf( |
||
| 484 | __( 'You can now save time spent logging in by connecting your WordPress.com account to %s.', 'jetpack' ), |
||
| 485 | esc_html( $site_name ) |
||
| 486 | ) |
||
| 487 | ); |
||
| 488 | ?> |
||
| 489 | </p> |
||
| 490 | <?php endif; ?> |
||
| 491 | </div> |
||
| 492 | |||
| 493 | <?php if ( ! Jetpack_SSO_Helpers::should_hide_login_form() ) : ?> |
||
| 494 | <div class="jetpack-sso-or"> |
||
| 495 | <span><?php esc_html_e( 'Or', 'jetpack' ); ?></span> |
||
| 496 | </div> |
||
| 497 | |||
| 498 | <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '1' ) ); ?>" class="jetpack-sso-toggle wpcom"> |
||
| 499 | <?php |
||
| 500 | esc_html_e( 'Log in with username and password', 'jetpack' ) |
||
| 501 | ?> |
||
| 502 | </a> |
||
| 503 | |||
| 504 | <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '0' ) ); ?>" class="jetpack-sso-toggle default"> |
||
| 505 | <?php |
||
| 506 | esc_html_e( 'Log in with WordPress.com', 'jetpack' ) |
||
| 507 | ?> |
||
| 508 | </a> |
||
| 509 | <?php endif; ?> |
||
| 510 | </div> |
||
| 511 | <?php |
||
| 512 | } |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Clear the cookies that store the profile information for the last |
||
| 516 | * WPCOM user to connect. |
||
| 517 | */ |
||
| 518 | static function clear_wpcom_profile_cookies() { |
||
| 519 | View Code Duplication | if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_name_' . COOKIEHASH ] ) ) { |
|
| 520 | setcookie( |
||
| 521 | 'jetpack_sso_wpcom_name_' . COOKIEHASH, |
||
| 522 | ' ', |
||
| 523 | time() - YEAR_IN_SECONDS, |
||
| 524 | COOKIEPATH, |
||
| 525 | COOKIE_DOMAIN |
||
| 526 | ); |
||
| 527 | } |
||
| 528 | |||
| 529 | View Code Duplication | if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH ] ) ) { |
|
| 530 | setcookie( |
||
| 531 | 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH, |
||
| 532 | ' ', |
||
| 533 | time() - YEAR_IN_SECONDS, |
||
| 534 | COOKIEPATH, |
||
| 535 | COOKIE_DOMAIN |
||
| 536 | ); |
||
| 537 | } |
||
| 538 | } |
||
| 539 | |||
| 540 | static function delete_connection_for_user( $user_id ) { |
||
| 541 | if ( ! $wpcom_user_id = get_user_meta( $user_id, 'wpcom_user_id', true ) ) { |
||
| 542 | return; |
||
| 543 | } |
||
| 544 | Jetpack::load_xml_rpc_client(); |
||
| 545 | $xml = new Jetpack_IXR_Client( array( |
||
| 546 | 'wpcom_user_id' => $user_id, |
||
| 547 | ) ); |
||
| 548 | $xml->query( 'jetpack.sso.removeUser', $wpcom_user_id ); |
||
| 549 | |||
| 550 | if ( $xml->isError() ) { |
||
| 551 | return false; |
||
| 552 | } |
||
| 553 | |||
| 554 | // Clean up local data stored for SSO |
||
| 555 | delete_user_meta( $user_id, 'wpcom_user_id' ); |
||
| 556 | delete_user_meta( $user_id, 'wpcom_user_data' ); |
||
| 557 | self::clear_wpcom_profile_cookies(); |
||
| 558 | |||
| 559 | return $xml->getResponse(); |
||
| 560 | } |
||
| 561 | |||
| 562 | View Code Duplication | static function request_initial_nonce() { |
|
| 563 | Jetpack::load_xml_rpc_client(); |
||
| 564 | $xml = new Jetpack_IXR_Client( array( |
||
| 565 | 'user_id' => get_current_user_id(), |
||
| 566 | ) ); |
||
| 567 | $xml->query( 'jetpack.sso.requestNonce' ); |
||
| 568 | |||
| 569 | if ( $xml->isError() ) { |
||
| 570 | return new WP_Error( $xml->getErrorCode(), $xml->getErrorMessage() ); |
||
| 571 | } |
||
| 572 | |||
| 573 | return $xml->getResponse(); |
||
| 574 | } |
||
| 575 | |||
| 576 | /** |
||
| 577 | * The function that actually handles the login! |
||
| 578 | */ |
||
| 579 | function handle_login() { |
||
| 580 | $wpcom_nonce = sanitize_key( $_GET['sso_nonce'] ); |
||
| 581 | $wpcom_user_id = (int) $_GET['user_id']; |
||
| 582 | |||
| 583 | Jetpack::load_xml_rpc_client(); |
||
| 584 | $xml = new Jetpack_IXR_Client( array( |
||
| 585 | 'user_id' => get_current_user_id(), |
||
| 586 | ) ); |
||
| 587 | $xml->query( 'jetpack.sso.validateResult', $wpcom_nonce, $wpcom_user_id ); |
||
| 588 | |||
| 589 | $user_data = $xml->isError() ? false : $xml->getResponse(); |
||
| 590 | if ( empty( $user_data ) ) { |
||
| 591 | add_filter( 'jetpack_sso_default_to_sso_login', '__return_false' ); |
||
| 592 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_invalid_response_data' ) ); |
||
| 593 | return; |
||
| 594 | } |
||
| 595 | |||
| 596 | $user_data = (object) $user_data; |
||
| 597 | $user = null; |
||
| 598 | |||
| 599 | /** |
||
| 600 | * Fires before Jetpack's SSO modifies the log in form. |
||
| 601 | * |
||
| 602 | * @module sso |
||
| 603 | * |
||
| 604 | * @since 2.6.0 |
||
| 605 | * |
||
| 606 | * @param object $user_data WordPress.com User information. |
||
| 607 | */ |
||
| 608 | do_action( 'jetpack_sso_pre_handle_login', $user_data ); |
||
| 609 | |||
| 610 | if ( Jetpack_SSO_Helpers::is_two_step_required() && 0 === (int) $user_data->two_step_enabled ) { |
||
| 611 | $this->user_data = $user_data; |
||
| 612 | |||
| 613 | JetpackTracking::record_user_event( 'sso_login_failed', array( |
||
| 614 | 'error_message' => 'error_msg_enable_two_step' |
||
| 615 | ) ); |
||
| 616 | |||
| 617 | /** This filter is documented in core/src/wp-includes/pluggable.php */ |
||
| 618 | do_action( 'wp_login_failed', $user_data->login ); |
||
| 619 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_msg_enable_two_step' ) ); |
||
| 620 | return; |
||
| 621 | } |
||
| 622 | |||
| 623 | $user_found_with = ''; |
||
| 624 | if ( empty( $user ) && isset( $user_data->external_user_id ) ) { |
||
| 625 | $user_found_with = 'external_user_id'; |
||
| 626 | $user = get_user_by( 'id', intval( $user_data->external_user_id ) ); |
||
| 627 | if ( $user ) { |
||
| 628 | update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); |
||
| 629 | } |
||
| 630 | } |
||
| 631 | |||
| 632 | // If we don't have one by wpcom_user_id, try by the email? |
||
| 633 | if ( empty( $user ) && Jetpack_SSO_Helpers::match_by_email() ) { |
||
| 634 | $user_found_with = 'match_by_email'; |
||
| 635 | $user = get_user_by( 'email', $user_data->email ); |
||
| 636 | if ( $user ) { |
||
| 637 | update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); |
||
| 638 | } |
||
| 639 | } |
||
| 640 | |||
| 641 | // If we've still got nothing, create the user. |
||
| 642 | if ( empty( $user ) && ( get_option( 'users_can_register' ) || Jetpack_SSO_Helpers::new_user_override() ) ) { |
||
| 643 | /** |
||
| 644 | * If not matching by email we still need to verify the email does not exist |
||
| 645 | * or this blows up |
||
| 646 | * |
||
| 647 | * If match_by_email is true, we know the email doesn't exist, as it would have |
||
| 648 | * been found in the first pass. If get_user_by( 'email' ) doesn't find the |
||
| 649 | * user, then we know that email is unused, so it's safe to add. |
||
| 650 | */ |
||
| 651 | if ( Jetpack_SSO_Helpers::match_by_email() || ! get_user_by( 'email', $user_data->email ) ) { |
||
| 652 | $user = Jetpack_SSO_Helpers::generate_user( $user_data ); |
||
| 653 | if ( ! $user ) { |
||
| 654 | JetpackTracking::record_user_event( 'sso_login_failed', array( |
||
| 655 | 'error_message' => 'could_not_create_username' |
||
| 656 | ) ); |
||
| 657 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_unable_to_create_user' ) ); |
||
| 658 | return; |
||
| 659 | } |
||
| 660 | |||
| 661 | $user_found_with = Jetpack_SSO_Helpers::new_user_override() |
||
| 662 | ? 'user_created_new_user_override' |
||
| 663 | : 'user_created_users_can_register'; |
||
| 664 | } else { |
||
| 665 | JetpackTracking::record_user_event( 'sso_login_failed', array( |
||
| 666 | 'error_message' => 'error_msg_email_already_exists' |
||
| 667 | ) ); |
||
| 668 | |||
| 669 | $this->user_data = $user_data; |
||
| 670 | add_action( 'login_message', array( 'Jetpack_SSO_Notices', 'error_msg_email_already_exists' ) ); |
||
| 671 | return; |
||
| 672 | } |
||
| 673 | } |
||
| 674 | |||
| 675 | /** |
||
| 676 | * Fires after we got login information from WordPress.com. |
||
| 677 | * |
||
| 678 | * @module sso |
||
| 679 | * |
||
| 680 | * @since 2.6.0 |
||
| 681 | * |
||
| 682 | * @param array $user Local User information. |
||
| 683 | * @param object $user_data WordPress.com User Login information. |
||
| 684 | */ |
||
| 685 | do_action( 'jetpack_sso_handle_login', $user, $user_data ); |
||
| 686 | |||
| 687 | if ( $user ) { |
||
| 688 | // Cache the user's details, so we can present it back to them on their user screen |
||
| 689 | update_user_meta( $user->ID, 'wpcom_user_data', $user_data ); |
||
| 690 | |||
| 691 | add_filter( 'auth_cookie_expiration', array( 'Jetpack_SSO_Helpers', 'extend_auth_cookie_expiration_for_sso' ) ); |
||
| 692 | wp_set_auth_cookie( $user->ID, true ); |
||
| 693 | remove_filter( 'auth_cookie_expiration', array( 'Jetpack_SSO_Helpers', 'extend_auth_cookie_expiration_for_sso' ) ); |
||
| 694 | |||
| 695 | /** This filter is documented in core/src/wp-includes/user.php */ |
||
| 696 | do_action( 'wp_login', $user->user_login, $user ); |
||
| 697 | |||
| 698 | wp_set_current_user( $user->ID ); |
||
| 699 | |||
| 700 | $_request_redirect_to = isset( $_REQUEST['redirect_to'] ) ? esc_url_raw( $_REQUEST['redirect_to'] ) : ''; |
||
| 701 | $redirect_to = user_can( $user, 'edit_posts' ) ? admin_url() : self::profile_page_url(); |
||
| 702 | |||
| 703 | // If we have a saved redirect to request in a cookie |
||
| 704 | if ( ! empty( $_COOKIE['jetpack_sso_redirect_to'] ) ) { |
||
| 705 | // Set that as the requested redirect to |
||
| 706 | $redirect_to = $_request_redirect_to = esc_url_raw( $_COOKIE['jetpack_sso_redirect_to'] ); |
||
| 707 | // And then purge it |
||
| 708 | setcookie( 'jetpack_sso_redirect_to', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 709 | } |
||
| 710 | |||
| 711 | $is_user_connected = Jetpack::is_user_connected( $user->ID ); |
||
| 712 | JetpackTracking::record_user_event( 'sso_user_logged_in', array( |
||
| 713 | 'user_found_with' => $user_found_with, |
||
| 714 | 'user_connected' => (bool) $is_user_connected, |
||
| 715 | 'user_role' => Jetpack::translate_current_user_to_role() |
||
| 716 | ) ); |
||
| 717 | |||
| 718 | if ( ! $is_user_connected ) { |
||
| 719 | $calypso_env = ! empty( $_GET['calypso_env'] ) |
||
| 720 | ? sanitize_key( $_GET['calypso_env'] ) |
||
| 721 | : ''; |
||
| 722 | |||
| 723 | wp_safe_redirect( |
||
| 724 | add_query_arg( |
||
| 725 | array( |
||
| 726 | 'redirect_to' => $redirect_to, |
||
| 727 | 'request_redirect_to' => $_request_redirect_to, |
||
| 728 | 'calypso_env' => $calypso_env, |
||
| 729 | 'jetpack-sso-auth-redirect' => '1', |
||
| 730 | ), |
||
| 731 | admin_url() |
||
| 732 | ) |
||
| 733 | ); |
||
| 734 | exit; |
||
| 735 | } |
||
| 736 | |||
| 737 | wp_safe_redirect( |
||
| 738 | /** This filter is documented in core/src/wp-login.php */ |
||
| 739 | apply_filters( 'login_redirect', $redirect_to, $_request_redirect_to, $user ) |
||
| 740 | ); |
||
| 741 | exit; |
||
|
0 ignored issues
–
show
The method
handle_login() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an Loading history...
|
|||
| 742 | } |
||
| 743 | |||
| 744 | add_filter( 'jetpack_sso_default_to_sso_login', '__return_false' ); |
||
| 745 | |||
| 746 | JetpackTracking::record_user_event( 'sso_login_failed', array( |
||
| 747 | 'error_message' => 'cant_find_user' |
||
| 748 | ) ); |
||
| 749 | |||
| 750 | $this->user_data = $user_data; |
||
| 751 | /** This filter is documented in core/src/wp-includes/pluggable.php */ |
||
| 752 | do_action( 'wp_login_failed', $user_data->login ); |
||
| 753 | add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'cant_find_user' ) ); |
||
| 754 | } |
||
| 755 | |||
| 756 | static function profile_page_url() { |
||
| 757 | return admin_url( 'profile.php' ); |
||
| 758 | } |
||
| 759 | |||
| 760 | /** |
||
| 761 | * Builds the "Login to WordPress.com" button that is displayed on the login page as well as user profile page. |
||
| 762 | * |
||
| 763 | * @param array $args An array of arguments to add to the SSO URL. |
||
| 764 | * @param boolean $is_primary Should the button have the `button-primary` class? |
||
| 765 | * @return string Returns the HTML markup for the button. |
||
| 766 | */ |
||
| 767 | function build_sso_button( $args = array(), $is_primary = false ) { |
||
| 768 | $url = $this->build_sso_button_url( $args ); |
||
| 769 | $classes = $is_primary |
||
| 770 | ? 'jetpack-sso button button-primary' |
||
| 771 | : 'jetpack-sso button'; |
||
| 772 | |||
| 773 | return sprintf( |
||
| 774 | '<a rel="nofollow" href="%1$s" class="%2$s"><span>%3$s %4$s</span></a>', |
||
| 775 | esc_url( $url ), |
||
| 776 | $classes, |
||
| 777 | '<span class="genericon genericon-wordpress"></span>', |
||
| 778 | esc_html__( 'Log in with WordPress.com', 'jetpack' ) |
||
| 779 | ); |
||
| 780 | } |
||
| 781 | |||
| 782 | /** |
||
| 783 | * Builds a URL with `jetpack-sso` action and option args which is used to setup SSO. |
||
| 784 | * |
||
| 785 | * @param array $args An array of arguments to add to the SSO URL. |
||
| 786 | * @return string The URL used for SSO. |
||
| 787 | */ |
||
| 788 | function build_sso_button_url( $args = array() ) { |
||
| 789 | $defaults = array( |
||
| 790 | 'action' => 'jetpack-sso', |
||
| 791 | ); |
||
| 792 | |||
| 793 | $args = wp_parse_args( $args, $defaults ); |
||
| 794 | |||
| 795 | if ( ! empty( $_GET['redirect_to'] ) ) { |
||
| 796 | $args['redirect_to'] = urlencode( esc_url_raw( $_GET['redirect_to'] ) ); |
||
| 797 | } |
||
| 798 | |||
| 799 | return add_query_arg( $args, wp_login_url() ); |
||
| 800 | } |
||
| 801 | |||
| 802 | /** |
||
| 803 | * Retrieves a WordPress.com SSO URL with appropriate query parameters or dies. |
||
| 804 | * |
||
| 805 | * @param boolean $reauth Should the user be forced to reauthenticate on WordPress.com? |
||
| 806 | * @param array $args Optional query parameters. |
||
| 807 | * @return string The WordPress.com SSO URL. |
||
| 808 | */ |
||
| 809 | function get_sso_url_or_die( $reauth = false, $args = array() ) { |
||
| 810 | if ( empty( $reauth ) ) { |
||
| 811 | $sso_redirect = $this->build_sso_url( $args ); |
||
| 812 | } else { |
||
| 813 | self::clear_wpcom_profile_cookies(); |
||
| 814 | $sso_redirect = $this->build_reauth_and_sso_url( $args ); |
||
| 815 | } |
||
| 816 | |||
| 817 | // If there was an error retrieving the SSO URL, then error. |
||
| 818 | if ( is_wp_error( $sso_redirect ) ) { |
||
| 819 | $error_message = sanitize_text_field( |
||
| 820 | sprintf( '%s: %s', $sso_redirect->get_error_code(), $sso_redirect->get_error_message() ) |
||
| 821 | ); |
||
| 822 | JetpackTracking::record_user_event( 'sso_login_redirect_failed', array( |
||
| 823 | 'error_message' => $error_message |
||
| 824 | ) ); |
||
| 825 | wp_die( $error_message ); |
||
| 826 | } |
||
| 827 | |||
| 828 | return $sso_redirect; |
||
| 829 | } |
||
| 830 | |||
| 831 | /** |
||
| 832 | * Build WordPress.com SSO URL with appropriate query parameters. |
||
| 833 | * |
||
| 834 | * @param array $args Optional query parameters. |
||
| 835 | * @return string WordPress.com SSO URL |
||
| 836 | */ |
||
| 837 | function build_sso_url( $args = array() ) { |
||
| 838 | $sso_nonce = ! empty( $args['sso_nonce'] ) ? $args['sso_nonce'] : self::request_initial_nonce(); |
||
| 839 | $defaults = array( |
||
| 840 | 'action' => 'jetpack-sso', |
||
| 841 | 'site_id' => Jetpack_Options::get_option( 'id' ), |
||
| 842 | 'sso_nonce' => $sso_nonce, |
||
| 843 | 'calypso_auth' => '1', |
||
| 844 | ); |
||
| 845 | |||
| 846 | $args = wp_parse_args( $args, $defaults ); |
||
| 847 | |||
| 848 | if ( is_wp_error( $args['sso_nonce'] ) ) { |
||
| 849 | return $args['sso_nonce']; |
||
| 850 | } |
||
| 851 | |||
| 852 | return add_query_arg( $args, 'https://wordpress.com/wp-login.php' ); |
||
| 853 | } |
||
| 854 | |||
| 855 | /** |
||
| 856 | * Build WordPress.com SSO URL with appropriate query parameters, |
||
| 857 | * including the parameters necessary to force the user to reauthenticate |
||
| 858 | * on WordPress.com. |
||
| 859 | * |
||
| 860 | * @param array $args Optional query parameters. |
||
| 861 | * @return string WordPress.com SSO URL |
||
| 862 | */ |
||
| 863 | function build_reauth_and_sso_url( $args = array() ) { |
||
| 864 | $sso_nonce = ! empty( $args['sso_nonce'] ) ? $args['sso_nonce'] : self::request_initial_nonce(); |
||
| 865 | $redirect = $this->build_sso_url( array( 'force_auth' => '1', 'sso_nonce' => $sso_nonce ) ); |
||
| 866 | |||
| 867 | if ( is_wp_error( $redirect ) ) { |
||
| 868 | return $redirect; |
||
| 869 | } |
||
| 870 | |||
| 871 | $defaults = array( |
||
| 872 | 'action' => 'jetpack-sso', |
||
| 873 | 'site_id' => Jetpack_Options::get_option( 'id' ), |
||
| 874 | 'sso_nonce' => $sso_nonce, |
||
| 875 | 'reauth' => '1', |
||
| 876 | 'redirect_to' => urlencode( $redirect ), |
||
| 877 | 'calypso_auth' => '1', |
||
| 878 | ); |
||
| 879 | |||
| 880 | $args = wp_parse_args( $args, $defaults ); |
||
| 881 | |||
| 882 | if ( is_wp_error( $args['sso_nonce'] ) ) { |
||
| 883 | return $args['sso_nonce']; |
||
| 884 | } |
||
| 885 | |||
| 886 | return add_query_arg( $args, 'https://wordpress.com/wp-login.php' ); |
||
| 887 | } |
||
| 888 | |||
| 889 | /** |
||
| 890 | * Determines local user associated with a given WordPress.com user ID. |
||
| 891 | * |
||
| 892 | * @since 2.6.0 |
||
| 893 | * |
||
| 894 | * @param int $wpcom_user_id User ID from WordPress.com |
||
| 895 | * @return object Local user object if found, null if not. |
||
| 896 | */ |
||
| 897 | static function get_user_by_wpcom_id( $wpcom_user_id ) { |
||
| 898 | $user_query = new WP_User_Query( array( |
||
| 899 | 'meta_key' => 'wpcom_user_id', |
||
| 900 | 'meta_value' => intval( $wpcom_user_id ), |
||
| 901 | 'number' => 1, |
||
| 902 | ) ); |
||
| 903 | |||
| 904 | $users = $user_query->get_results(); |
||
| 905 | return $users ? array_shift( $users ) : null; |
||
| 906 | } |
||
| 907 | |||
| 908 | /** |
||
| 909 | * When jetpack-sso-auth-redirect query parameter is set, will redirect user to |
||
| 910 | * WordPress.com authorization flow. |
||
| 911 | * |
||
| 912 | * We redirect here instead of in handle_login() because Jetpack::init()->build_connect_url |
||
| 913 | * calls menu_page_url() which doesn't work properly until admin menus are registered. |
||
| 914 | */ |
||
| 915 | function maybe_authorize_user_after_sso() { |
||
| 916 | if ( empty( $_GET['jetpack-sso-auth-redirect'] ) ) { |
||
| 917 | return; |
||
| 918 | } |
||
| 919 | |||
| 920 | $redirect_to = ! empty( $_GET['redirect_to'] ) ? esc_url_raw( $_GET['redirect_to'] ) : admin_url(); |
||
| 921 | $request_redirect_to = ! empty( $_GET['request_redirect_to'] ) ? esc_url_raw( $_GET['request_redirect_to'] ) : $redirect_to; |
||
| 922 | |||
| 923 | /** This filter is documented in core/src/wp-login.php */ |
||
| 924 | $redirect_after_auth = apply_filters( 'login_redirect', $redirect_to, $request_redirect_to, wp_get_current_user() ); |
||
| 925 | |||
| 926 | /** |
||
| 927 | * Since we are passing this redirect to WordPress.com and therefore can not use wp_safe_redirect(), |
||
| 928 | * let's sanitize it here to make sure it's safe. If the redirect is not safe, then use admin_url(). |
||
| 929 | */ |
||
| 930 | $redirect_after_auth = wp_sanitize_redirect( $redirect_after_auth ); |
||
| 931 | $redirect_after_auth = wp_validate_redirect( $redirect_after_auth, admin_url() ); |
||
| 932 | |||
| 933 | /** |
||
| 934 | * Return the raw connect URL with our redirect and attribute connection to SSO. |
||
| 935 | */ |
||
| 936 | $connect_url = Jetpack::init()->build_connect_url( true, $redirect_after_auth, 'sso' ); |
||
| 937 | |||
| 938 | add_filter( 'allowed_redirect_hosts', array( 'Jetpack_SSO_Helpers', 'allowed_redirect_hosts' ) ); |
||
| 939 | wp_safe_redirect( $connect_url ); |
||
| 940 | exit; |
||
| 941 | } |
||
| 942 | |||
| 943 | /** |
||
| 944 | * Cache user's display name and Gravatar so it can be displayed on the login screen. These cookies are |
||
| 945 | * stored when the user logs out, and then deleted when the user logs in. |
||
| 946 | */ |
||
| 947 | function store_wpcom_profile_cookies_on_logout() { |
||
| 948 | if ( ! Jetpack::is_user_connected( get_current_user_id() ) ) { |
||
| 949 | return; |
||
| 950 | } |
||
| 951 | |||
| 952 | $user_data = $this->get_user_data( get_current_user_id() ); |
||
| 953 | if ( ! $user_data ) { |
||
| 954 | return; |
||
| 955 | } |
||
| 956 | |||
| 957 | setcookie( |
||
| 958 | 'jetpack_sso_wpcom_name_' . COOKIEHASH, |
||
| 959 | $user_data->display_name, |
||
| 960 | time() + WEEK_IN_SECONDS, |
||
| 961 | COOKIEPATH, |
||
| 962 | COOKIE_DOMAIN |
||
| 963 | ); |
||
| 964 | |||
| 965 | setcookie( |
||
| 966 | 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH, |
||
| 967 | get_avatar_url( |
||
| 968 | $user_data->email, |
||
| 969 | array( 'size' => 144, 'default' => 'mystery' ) |
||
| 970 | ), |
||
| 971 | time() + WEEK_IN_SECONDS, |
||
| 972 | COOKIEPATH, |
||
| 973 | COOKIE_DOMAIN |
||
| 974 | ); |
||
| 975 | } |
||
| 976 | |||
| 977 | /** |
||
| 978 | * Determines if a local user is connected to WordPress.com |
||
| 979 | * |
||
| 980 | * @since 2.8 |
||
| 981 | * @param integer $user_id - Local user id |
||
| 982 | * @return boolean |
||
| 983 | **/ |
||
| 984 | public function is_user_connected( $user_id ) { |
||
| 985 | return $this->get_user_data( $user_id ); |
||
| 986 | } |
||
| 987 | |||
| 988 | /** |
||
| 989 | * Retrieves a user's WordPress.com data |
||
| 990 | * |
||
| 991 | * @since 2.8 |
||
| 992 | * @param integer $user_id - Local user id |
||
| 993 | * @return mixed null or stdClass |
||
| 994 | **/ |
||
| 995 | public function get_user_data( $user_id ) { |
||
| 996 | return get_user_meta( $user_id, 'wpcom_user_data', true ); |
||
| 997 | } |
||
| 998 | } |
||
| 999 | |||
| 1000 | Jetpack_SSO::get_instance(); |
||
| 1001 |
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exitexpression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.