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 | |||
| 3 | /** |
||
| 4 | * Module Name: Single Sign On |
||
| 5 | * Module Description: Secure user authentication. |
||
| 6 | * Jumpstart Description: Lets you log in to all your Jetpack-enabled sites with one click using your WordPress.com account. |
||
| 7 | * Sort Order: 30 |
||
| 8 | * Recommendation Order: 5 |
||
| 9 | * First Introduced: 2.6 |
||
| 10 | * Requires Connection: Yes |
||
| 11 | * Auto Activate: No |
||
| 12 | * Module Tags: Developers |
||
| 13 | * Feature: Jumpstart, Performance-Security |
||
| 14 | * Additional Search Queries: sso, single sign on, login, log in |
||
| 15 | */ |
||
| 16 | |||
| 17 | class Jetpack_SSO { |
||
| 18 | static $instance = null; |
||
| 19 | |||
| 20 | private function __construct() { |
||
| 21 | |||
| 22 | self::$instance = $this; |
||
| 23 | |||
| 24 | add_action( 'admin_init', array( $this, 'admin_init' ) ); |
||
| 25 | add_action( 'admin_init', array( $this, 'register_settings' ) ); |
||
| 26 | add_action( 'login_init', array( $this, 'login_init' ) ); |
||
| 27 | add_action( 'delete_user', array( $this, 'delete_connection_for_user' ) ); |
||
| 28 | add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) ); |
||
| 29 | add_action( 'init', array( $this, 'maybe_logout_user' ), 5 ); |
||
| 30 | add_action( 'jetpack_modules_loaded', array( $this, 'module_configure_button' ) ); |
||
| 31 | |||
| 32 | // Adding this action so that on login_init, the action won't be sanitized out of the $action global. |
||
| 33 | add_action( 'login_form_jetpack-sso', '__return_true' ); |
||
| 34 | |||
| 35 | if ( |
||
| 36 | $this->should_hide_login_form() && |
||
| 37 | /** |
||
| 38 | * Filter the display of the disclaimer message appearing when default WordPress login form is disabled. |
||
| 39 | * |
||
| 40 | * @module sso |
||
| 41 | * |
||
| 42 | * @since 2.8.0 |
||
| 43 | * |
||
| 44 | * @param bool true Should the disclaimer be displayed. Default to true. |
||
| 45 | */ |
||
| 46 | apply_filters( 'jetpack_sso_display_disclaimer', true ) |
||
| 47 | ) { |
||
| 48 | add_action( 'login_message', array( $this, 'msg_login_by_jetpack' ) ); |
||
| 49 | } |
||
| 50 | } |
||
| 51 | |||
| 52 | /** |
||
| 53 | * Returns the single instance of the Jetpack_SSO object |
||
| 54 | * |
||
| 55 | * @since 2.8 |
||
| 56 | * @return Jetpack_SSO |
||
| 57 | **/ |
||
| 58 | public static function get_instance() { |
||
| 59 | if( !is_null( self::$instance ) ) |
||
| 60 | return self::$instance; |
||
| 61 | |||
| 62 | return self::$instance = new Jetpack_SSO; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Add configure button and functionality to the module card on the Jetpack screen |
||
| 67 | **/ |
||
| 68 | public static function module_configure_button() { |
||
| 69 | Jetpack::enable_module_configurable( __FILE__ ); |
||
| 70 | Jetpack::module_configuration_load( __FILE__, array( __CLASS__, 'module_configuration_load' ) ); |
||
| 71 | Jetpack::module_configuration_head( __FILE__, array( __CLASS__, 'module_configuration_head' ) ); |
||
| 72 | Jetpack::module_configuration_screen( __FILE__, array( __CLASS__, 'module_configuration_screen' ) ); |
||
| 73 | } |
||
| 74 | |||
| 75 | public static function module_configuration_load() { |
||
| 76 | // wp_safe_redirect( admin_url( 'options-general.php#configure-sso' ) ); |
||
| 77 | // exit; |
||
| 78 | } |
||
| 79 | |||
| 80 | public static function module_configuration_head() {} |
||
| 81 | |||
| 82 | public static function module_configuration_screen() { |
||
| 83 | ?> |
||
| 84 | <form method="post" action="options.php"> |
||
| 85 | <?php settings_fields( 'jetpack-sso' ); ?> |
||
| 86 | <?php do_settings_sections( 'jetpack-sso' ); ?> |
||
| 87 | <?php submit_button(); ?> |
||
| 88 | </form> |
||
| 89 | <?php |
||
| 90 | } |
||
| 91 | |||
| 92 | /** |
||
| 93 | * If jetpack_force_logout == 1 in current user meta the user will be forced |
||
| 94 | * to logout and reauthenticate with the site. |
||
| 95 | **/ |
||
| 96 | public function maybe_logout_user() { |
||
| 97 | global $current_user; |
||
| 98 | |||
| 99 | if( 1 == $current_user->jetpack_force_logout ) { |
||
| 100 | delete_user_meta( $current_user->ID, 'jetpack_force_logout' ); |
||
| 101 | self::delete_connection_for_user( $current_user->ID ); |
||
| 102 | wp_logout(); |
||
| 103 | wp_safe_redirect( wp_login_url() ); |
||
| 104 | } |
||
| 105 | } |
||
| 106 | |||
| 107 | |||
| 108 | /** |
||
| 109 | * Adds additional methods the WordPress xmlrpc API for handling SSO specific features |
||
| 110 | * |
||
| 111 | * @param array $methods |
||
| 112 | * @return array |
||
| 113 | **/ |
||
| 114 | public function xmlrpc_methods( $methods ) { |
||
| 115 | $methods['jetpack.userDisconnect'] = array( $this, 'xmlrpc_user_disconnect' ); |
||
| 116 | return $methods; |
||
| 117 | } |
||
| 118 | |||
| 119 | /** |
||
| 120 | * Marks a user's profile for disconnect from WordPress.com and forces a logout |
||
| 121 | * the next time the user visits the site. |
||
| 122 | **/ |
||
| 123 | public function xmlrpc_user_disconnect( $user_id ) { |
||
| 124 | $user_query = new WP_User_Query( |
||
| 125 | array( |
||
| 126 | 'meta_key' => 'wpcom_user_id', |
||
| 127 | 'meta_value' => $user_id |
||
| 128 | ) |
||
| 129 | ); |
||
| 130 | $user = $user_query->get_results(); |
||
| 131 | $user = $user[0]; |
||
| 132 | |||
| 133 | |||
| 134 | if( $user instanceof WP_User ) { |
||
| 135 | $user = wp_set_current_user( $user->ID ); |
||
| 136 | update_user_meta( $user->ID, 'jetpack_force_logout', '1' ); |
||
| 137 | self::delete_connection_for_user( $user->ID ); |
||
| 138 | return true; |
||
| 139 | } |
||
| 140 | return false; |
||
| 141 | } |
||
| 142 | |||
| 143 | /** |
||
| 144 | * Adds settings fields to Settings > General > Single Sign On that allows users to |
||
| 145 | * turn off the login form on wp-login.php |
||
| 146 | * |
||
| 147 | * @since 2.7 |
||
| 148 | **/ |
||
| 149 | public function register_settings() { |
||
| 150 | |||
| 151 | add_settings_section( |
||
| 152 | 'jetpack_sso_settings', |
||
| 153 | __( 'Single Sign On' , 'jetpack' ), |
||
| 154 | '__return_false', |
||
| 155 | 'jetpack-sso' |
||
| 156 | ); |
||
| 157 | |||
| 158 | /* |
||
| 159 | * Settings > General > Single Sign On |
||
| 160 | * Checkbox for Remove default login form |
||
| 161 | */ |
||
| 162 | /* Hide in 2.9 |
||
| 163 | register_setting( |
||
| 164 | 'general', |
||
| 165 | 'jetpack_sso_remove_login_form', |
||
| 166 | array( $this, 'validate_settings_remove_login_form_checkbox' ) |
||
| 167 | ); |
||
| 168 | |||
| 169 | add_settings_field( |
||
| 170 | 'jetpack_sso_remove_login_form', |
||
| 171 | __( 'Remove default login form?' , 'jetpack' ), |
||
| 172 | array( $this, 'render_remove_login_form_checkbox' ), |
||
| 173 | 'general', |
||
| 174 | 'jetpack_sso_settings' |
||
| 175 | ); |
||
| 176 | */ |
||
| 177 | |||
| 178 | /* |
||
| 179 | * Settings > General > Single Sign On |
||
| 180 | * Require two step authentication |
||
| 181 | */ |
||
| 182 | register_setting( |
||
| 183 | 'jetpack-sso', |
||
| 184 | 'jetpack_sso_require_two_step', |
||
| 185 | array( $this, 'validate_jetpack_sso_require_two_step' ) |
||
| 186 | ); |
||
| 187 | |||
| 188 | add_settings_field( |
||
| 189 | 'jetpack_sso_require_two_step', |
||
| 190 | '', // __( 'Require Two-Step Authentication' , 'jetpack' ), |
||
| 191 | array( $this, 'render_require_two_step' ), |
||
| 192 | 'jetpack-sso', |
||
| 193 | 'jetpack_sso_settings' |
||
| 194 | ); |
||
| 195 | |||
| 196 | |||
| 197 | /* |
||
| 198 | * Settings > General > Single Sign On |
||
| 199 | */ |
||
| 200 | register_setting( |
||
| 201 | 'jetpack-sso', |
||
| 202 | 'jetpack_sso_match_by_email', |
||
| 203 | array( $this, 'validate_jetpack_sso_match_by_email' ) |
||
| 204 | ); |
||
| 205 | |||
| 206 | add_settings_field( |
||
| 207 | 'jetpack_sso_match_by_email', |
||
| 208 | '', // __( 'Match by Email' , 'jetpack' ), |
||
| 209 | array( $this, 'render_match_by_email' ), |
||
| 210 | 'jetpack-sso', |
||
| 211 | 'jetpack_sso_settings' |
||
| 212 | ); |
||
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Builds the display for the checkbox allowing user to require two step |
||
| 217 | * auth be enabled on WordPress.com accounts before login. Displays in Settings > General |
||
| 218 | * |
||
| 219 | * @since 2.7 |
||
| 220 | **/ |
||
| 221 | View Code Duplication | public function render_require_two_step() { |
|
| 222 | echo '<label>'; |
||
| 223 | echo '<input type="checkbox" name="jetpack_sso_require_two_step" ' . checked( 1 == get_option( 'jetpack_sso_require_two_step' ), true, false ) . '> '; |
||
| 224 | esc_html_e( 'Require Two-Step Authentication' , 'jetpack' ); |
||
| 225 | echo '</label>'; |
||
| 226 | } |
||
| 227 | |||
| 228 | /** |
||
| 229 | * Validate the require two step checkbox in Settings > General |
||
| 230 | * |
||
| 231 | * @since 2.7 |
||
| 232 | * @return boolean |
||
| 233 | **/ |
||
| 234 | public function validate_jetpack_sso_require_two_step( $input ) { |
||
| 235 | return ( ! empty( $input ) ) ? 1 : 0; |
||
| 236 | } |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Builds the display for the checkbox allowing the user to allow matching logins by email |
||
| 240 | * Displays in Settings > General |
||
| 241 | * |
||
| 242 | * @since 2.9 |
||
| 243 | **/ |
||
| 244 | View Code Duplication | public function render_match_by_email() { |
|
| 245 | echo '<label>'; |
||
| 246 | echo '<input type="checkbox" name="jetpack_sso_match_by_email"' . checked( 1 == get_option( 'jetpack_sso_match_by_email' ), true, false) . '> '; |
||
| 247 | esc_html_e( 'Match by Email', 'jetpack' ); |
||
| 248 | echo '</label>'; |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * Validate the match by email check in Settings > General |
||
| 253 | * |
||
| 254 | * @since 2.9 |
||
| 255 | * @return boolean |
||
| 256 | **/ |
||
| 257 | public function validate_jetpack_sso_match_by_email( $input ) { |
||
| 258 | return ( ! empty( $input ) ) ? 1 : 0; |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Builds the display for the checkbox allowing users to remove the default |
||
| 263 | * WordPress login form from wp-login.php. Displays in Settings > General |
||
| 264 | * |
||
| 265 | * @since 2.7 |
||
| 266 | **/ |
||
| 267 | public function render_remove_login_form_checkbox() { |
||
| 268 | if( $this->is_user_connected( get_current_user_id() ) ) { |
||
| 269 | echo '<a name="configure-sso"></a>'; |
||
| 270 | echo '<input type="checkbox" name="jetpack_sso_remove_login_form[remove_login_form]" ' . checked( 1 == get_option( 'jetpack_sso_remove_login_form' ), true, false ) . '>'; |
||
| 271 | echo '<p class="description">Removes default login form and disallows login via POST</p>'; |
||
| 272 | } else { |
||
| 273 | echo 'Your account must be connected to WordPress.com before disabling the login form.'; |
||
| 274 | echo '<br/>' . $this->button(); |
||
| 275 | } |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * Validate settings input from Settings > General |
||
| 280 | * |
||
| 281 | * @since 2.7 |
||
| 282 | * @return boolean |
||
| 283 | **/ |
||
| 284 | public function validate_settings_remove_login_form_checkbox( $input ) { |
||
| 285 | return ( isset( $input['remove_login_form'] ) )? 1: 0; |
||
| 286 | } |
||
| 287 | |||
| 288 | /** |
||
| 289 | * Removes 'Lost your password?' text from the login form if user |
||
| 290 | * does not want to show the login form |
||
| 291 | * |
||
| 292 | * @since 2.7 |
||
| 293 | * @return string |
||
| 294 | **/ |
||
| 295 | public function remove_lost_password_text( $text ) { |
||
| 296 | if( 'Lost your password?' == $text ) |
||
| 297 | $text = ''; |
||
| 298 | return $text; |
||
| 299 | } |
||
| 300 | |||
| 301 | /** |
||
| 302 | * Checks to determine if the user wants to login on wp-login |
||
| 303 | * |
||
| 304 | * This function mostly exists to cover the exceptions to login |
||
| 305 | * that may exist as other parameters to $_GET[action] as $_GET[action] |
||
| 306 | * does not have to exist. By default WordPress assumes login if an action |
||
| 307 | * is not set, however this may not be true, as in the case of logout |
||
| 308 | * where $_GET[loggedout] is instead set |
||
| 309 | * |
||
| 310 | * @return boolean |
||
| 311 | **/ |
||
| 312 | private function wants_to_login() { |
||
| 313 | $wants_to_login = false; |
||
| 314 | |||
| 315 | // Cover default WordPress behavior |
||
| 316 | $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login'; |
||
| 317 | |||
| 318 | // And now the exceptions |
||
| 319 | $action = isset( $_GET['loggedout'] ) ? 'loggedout' : $action; |
||
| 320 | |||
| 321 | if( 'login' == $action ) { |
||
| 322 | $wants_to_login = true; |
||
| 323 | } |
||
| 324 | |||
| 325 | return $wants_to_login; |
||
| 326 | } |
||
| 327 | |||
| 328 | private function bypass_login_forward_wpcom() { |
||
| 329 | /** |
||
| 330 | * Redirect the site's log in form to WordPress.com's log in form. |
||
| 331 | * |
||
| 332 | * @module sso |
||
| 333 | * |
||
| 334 | * @since 3.1.0 |
||
| 335 | * |
||
| 336 | * @param bool false Should the site's log in form be automatically forwarded to WordPress.com's log in form. |
||
| 337 | */ |
||
| 338 | return apply_filters( 'jetpack_sso_bypass_login_forward_wpcom', false ); |
||
| 339 | } |
||
| 340 | |||
| 341 | function login_init() { |
||
| 342 | global $action; |
||
| 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'] ) && $this->bypass_login_forward_wpcom() ) { |
||
| 350 | add_filter( 'jetpack_remove_login_form', '__return_true' ); |
||
| 351 | add_filter( 'gettext', array( $this, 'remove_lost_password_text' ) ); |
||
| 352 | } |
||
| 353 | |||
| 354 | /** |
||
| 355 | * Check to see if the site admin wants to automagically forward the user |
||
| 356 | * to the WordPress.com login page AND that the request to wp-login.php |
||
| 357 | * is not something other than login (Like logout!) |
||
| 358 | */ |
||
| 359 | if ( |
||
| 360 | $this->wants_to_login() |
||
| 361 | && $this->bypass_login_forward_wpcom() |
||
| 362 | ) { |
||
| 363 | add_filter( 'allowed_redirect_hosts', array( $this, 'allowed_redirect_hosts' ) ); |
||
| 364 | $this->maybe_save_cookie_redirect(); |
||
| 365 | wp_safe_redirect( $this->build_sso_url() ); |
||
| 366 | } |
||
| 367 | |||
| 368 | if ( 'login' === $action ) { |
||
| 369 | wp_enqueue_script( 'jquery' ); |
||
| 370 | wp_enqueue_style( 'genericons' ); |
||
| 371 | add_action( 'login_footer', array( $this, 'login_form' ) ); |
||
| 372 | add_action( 'login_footer', array( $this, 'login_footer' ) ); |
||
| 373 | /* |
||
| 374 | if ( get_option( 'jetpack_sso_remove_login_form' ) ) { |
||
| 375 | // Check to see if the user is attempting to login via the default login form. |
||
| 376 | // If so we need to deny it and forward elsewhere. |
||
| 377 | if( isset( $_REQUEST['wp-submit'] ) && 'Log In' == $_REQUEST['wp-submit'] ) { |
||
| 378 | wp_die( 'Login not permitted by this method. '); |
||
| 379 | } |
||
| 380 | add_filter( 'gettext', array( $this, 'remove_lost_password_text' ) ); |
||
| 381 | } |
||
| 382 | */ |
||
| 383 | } elseif ( 'jetpack-sso' === $action ) { |
||
| 384 | if ( isset( $_GET['result'], $_GET['user_id'], $_GET['sso_nonce'] ) && 'success' == $_GET['result'] ) { |
||
| 385 | $this->handle_login(); |
||
| 386 | wp_enqueue_script( 'jquery' ); |
||
| 387 | wp_enqueue_style( 'genericons' ); |
||
| 388 | add_action( 'login_footer', array( $this, 'login_form' ) ); |
||
| 389 | add_action( 'login_footer', array( $this, 'login_footer' ) ); |
||
| 390 | } else { |
||
| 391 | if ( Jetpack::check_identity_crisis() ) { |
||
| 392 | wp_die( __( "Error: This site's Jetpack connection is currently experiencing problems.", 'jetpack' ) ); |
||
| 393 | } else { |
||
| 394 | $this->maybe_save_cookie_redirect(); |
||
| 395 | // Is it wiser to just use wp_redirect than do this runaround to wp_safe_redirect? |
||
| 396 | add_filter( 'allowed_redirect_hosts', array( $this, 'allowed_redirect_hosts' ) ); |
||
| 397 | wp_safe_redirect( $this->build_sso_url() ); |
||
| 398 | } |
||
| 399 | } |
||
| 400 | } |
||
| 401 | } |
||
| 402 | |||
| 403 | /** |
||
| 404 | * Conditionally save the redirect_to url as a cookie. |
||
| 405 | */ |
||
| 406 | public static function maybe_save_cookie_redirect() { |
||
| 407 | if ( headers_sent() ) { |
||
| 408 | return new WP_Error( 'headers_sent', __( 'Cannot deal with cookie redirects, as headers are already sent.', 'jetpack' ) ); |
||
| 409 | } |
||
| 410 | |||
| 411 | // If we have something to redirect to |
||
| 412 | if ( ! empty( $_GET['redirect_to'] ) ) { |
||
| 413 | $url = esc_url_raw( $_GET['redirect_to'] ); |
||
| 414 | setcookie( 'jetpack_sso_redirect_to', $url, time() + HOUR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, false, true ); |
||
| 415 | // Otherwise, if it's already set |
||
| 416 | } elseif ( ! empty( $_COOKIE['jetpack_sso_redirect_to'] ) ) { |
||
| 417 | // Purge it. |
||
| 418 | setcookie( 'jetpack_sso_redirect_to', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 419 | } |
||
| 420 | |||
| 421 | if ( ! empty( $_GET['rememberme'] ) ) { |
||
| 422 | setcookie( 'jetpack_sso_remember_me', '1', time() + HOUR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, false, true ); |
||
| 423 | } elseif ( ! empty( $_COOKIE['jetpack_sso_remember_me'] ) ) { |
||
| 424 | setcookie( 'jetpack_sso_remember_me', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 425 | } |
||
| 426 | } |
||
| 427 | |||
| 428 | /** |
||
| 429 | * Determine if the login form should be hidden or not |
||
| 430 | * |
||
| 431 | * Method is private only because it is only used in this class so far. |
||
| 432 | * Feel free to change it later |
||
| 433 | * |
||
| 434 | * @return bool |
||
| 435 | **/ |
||
| 436 | private function should_hide_login_form() { |
||
| 437 | /** |
||
| 438 | * Remove the default log in form, only leave the WordPress.com log in button. |
||
| 439 | * |
||
| 440 | * @module sso |
||
| 441 | * |
||
| 442 | * @since 3.1.0 |
||
| 443 | * |
||
| 444 | * @param bool get_option( 'jetpack_sso_remove_login_form', false ) Should the default log in form be removed. Default to false. |
||
| 445 | */ |
||
| 446 | return apply_filters( 'jetpack_remove_login_form', get_option( 'jetpack_sso_remove_login_form', false ) ); |
||
| 447 | } |
||
| 448 | |||
| 449 | function login_form() { |
||
| 450 | $classes = ''; |
||
| 451 | |||
| 452 | if( $this->should_hide_login_form() ) { |
||
| 453 | $classes .= ' forced-sso'; |
||
| 454 | } |
||
| 455 | echo '<div class="jetpack-sso-wrap' . $classes . '">' . $this->button() . '</div>'; |
||
| 456 | } |
||
| 457 | |||
| 458 | function login_footer() { |
||
| 459 | $hide_login_form = $this->should_hide_login_form(); |
||
| 460 | ?> |
||
| 461 | <style> |
||
| 462 | #loginform { |
||
| 463 | overflow: hidden; |
||
| 464 | padding-bottom: 26px; |
||
| 465 | } |
||
| 466 | .jetpack-sso-wrap { |
||
| 467 | <?php if ( $hide_login_form ) : ?> |
||
| 468 | text-align: center; |
||
| 469 | <?php else : ?> |
||
| 470 | float: right; |
||
| 471 | <?php endif; ?> |
||
| 472 | margin: 1em 0 0; |
||
| 473 | clear: right; |
||
| 474 | display: block; |
||
| 475 | } |
||
| 476 | |||
| 477 | <?php if ( $hide_login_form ) : ?> |
||
| 478 | .forced-sso .jetpack-sso.button { |
||
| 479 | font-size: 16px; |
||
| 480 | line-height: 27px; |
||
| 481 | height: 37px; |
||
| 482 | padding: 5px 12px 6px 47px; |
||
| 483 | } |
||
| 484 | .forced-sso .jetpack-sso.button:before { |
||
| 485 | font-size: 28px !important; |
||
| 486 | height: 37px; |
||
| 487 | padding: 5px 5px 4px; |
||
| 488 | width: 37px; |
||
| 489 | } |
||
| 490 | <?php endif; ?> |
||
| 491 | </style> |
||
| 492 | <script> |
||
| 493 | jQuery(document).ready(function($){ |
||
| 494 | <?php if ( $hide_login_form ) : ?> |
||
| 495 | $( '#loginform' ).empty(); |
||
| 496 | <?php endif; ?> |
||
| 497 | $( '#loginform' ).append( $( '.jetpack-sso-wrap' ) ); |
||
| 498 | |||
| 499 | var $rememberme = $( '#rememberme' ), |
||
| 500 | $ssoButton = $( 'a.jetpack-sso.button' ); |
||
| 501 | |||
| 502 | $rememberme.on( 'change', function() { |
||
| 503 | var url = $ssoButton.prop( 'href' ), |
||
| 504 | isChecked = $rememberme.prop( 'checked' ) ? 1 : 0; |
||
| 505 | |||
| 506 | if ( url.match( /&rememberme=\d/ ) ) { |
||
| 507 | url = url.replace( /&rememberme=\d/, '&rememberme=' + isChecked ); |
||
| 508 | } else { |
||
| 509 | url += '&rememberme=' + isChecked; |
||
| 510 | } |
||
| 511 | |||
| 512 | $ssoButton.prop( 'href', url ); |
||
| 513 | } ).change(); |
||
| 514 | |||
| 515 | }); |
||
| 516 | </script> |
||
| 517 | <?php |
||
| 518 | } |
||
| 519 | |||
| 520 | View Code Duplication | static function delete_connection_for_user( $user_id ) { |
|
| 521 | if ( ! $wpcom_user_id = get_user_meta( $user_id, 'wpcom_user_id', true ) ) { |
||
| 522 | return; |
||
| 523 | } |
||
| 524 | Jetpack::load_xml_rpc_client(); |
||
| 525 | $xml = new Jetpack_IXR_Client( array( |
||
| 526 | 'user_id' => $user_id |
||
| 527 | ) ); |
||
| 528 | $xml->query( 'jetpack.sso.removeUser', $wpcom_user_id ); |
||
| 529 | |||
| 530 | if ( $xml->isError() ) { |
||
| 531 | return false; |
||
| 532 | } |
||
| 533 | |||
| 534 | return $xml->getResponse(); |
||
| 535 | } |
||
| 536 | |||
| 537 | View Code Duplication | static function request_initial_nonce() { |
|
| 538 | Jetpack::load_xml_rpc_client(); |
||
| 539 | $xml = new Jetpack_IXR_Client( array( |
||
| 540 | 'user_id' => get_current_user_id() |
||
| 541 | ) ); |
||
| 542 | $xml->query( 'jetpack.sso.requestNonce' ); |
||
| 543 | |||
| 544 | if ( $xml->isError() ) { |
||
| 545 | wp_die( sprintf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() ) ); |
||
| 546 | } |
||
| 547 | |||
| 548 | return $xml->getResponse(); |
||
| 549 | } |
||
| 550 | |||
| 551 | /** |
||
| 552 | * The function that actually handles the login! |
||
| 553 | */ |
||
| 554 | function handle_login() { |
||
| 555 | $wpcom_nonce = sanitize_key( $_GET['sso_nonce'] ); |
||
| 556 | $wpcom_user_id = (int) $_GET['user_id']; |
||
| 557 | $result = sanitize_key( $_GET['result'] ); |
||
| 558 | |||
| 559 | Jetpack::load_xml_rpc_client(); |
||
| 560 | $xml = new Jetpack_IXR_Client( array( |
||
| 561 | 'user_id' => get_current_user_id() |
||
| 562 | ) ); |
||
| 563 | $xml->query( 'jetpack.sso.validateResult', $wpcom_nonce, $wpcom_user_id ); |
||
| 564 | |||
| 565 | if ( $xml->isError() ) { |
||
| 566 | wp_die( sprintf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() ) ); |
||
| 567 | } |
||
| 568 | |||
| 569 | $user_data = $xml->getResponse(); |
||
| 570 | |||
| 571 | if ( empty( $user_data ) ) { |
||
| 572 | wp_die( __( 'Error, invalid response data.', 'jetpack' ) ); |
||
| 573 | } |
||
| 574 | |||
| 575 | $user_data = (object) $user_data; |
||
| 576 | $user = null; |
||
| 577 | |||
| 578 | /** |
||
| 579 | * Fires before Jetpack's SSO modifies the log in form. |
||
| 580 | * |
||
| 581 | * @module sso |
||
| 582 | * |
||
| 583 | * @since 2.6.0 |
||
| 584 | * |
||
| 585 | * @param object $user_data User login information. |
||
| 586 | */ |
||
| 587 | do_action( 'jetpack_sso_pre_handle_login', $user_data ); |
||
| 588 | |||
| 589 | /** |
||
| 590 | * Is it required to have 2-step authentication enabled on WordPress.com to use SSO? |
||
| 591 | * |
||
| 592 | * @module sso |
||
| 593 | * |
||
| 594 | * @since 2.8.0 |
||
| 595 | * |
||
| 596 | * @param bool get_option( 'jetpack_sso_require_two_step' ) Does SSO require 2-step authentication? |
||
| 597 | */ |
||
| 598 | $require_two_step = apply_filters( 'jetpack_sso_require_two_step', get_option( 'jetpack_sso_require_two_step' ) ); |
||
| 599 | if( $require_two_step && 0 == (int) $user_data->two_step_enabled ) { |
||
| 600 | $this->user_data = $user_data; |
||
| 601 | /** This filter is documented in core/src/wp-includes/pluggable.php */ |
||
| 602 | do_action( 'wp_login_failed', $user_data->login ); |
||
| 603 | add_action( 'login_message', array( $this, 'error_msg_enable_two_step' ) ); |
||
| 604 | return; |
||
| 605 | } |
||
| 606 | |||
| 607 | if ( isset( $_GET['state'] ) && ( 0 < strpos( $_GET['state'], '|' ) ) ) { |
||
| 608 | list( $state, $nonce ) = explode( '|', $_GET['state'] ); |
||
| 609 | |||
| 610 | if ( wp_verify_nonce( $nonce, $state ) ) { |
||
| 611 | if ( 'sso-link-user' == $state ) { |
||
| 612 | $user = wp_get_current_user(); |
||
| 613 | update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); |
||
| 614 | add_filter( 'login_redirect', array( __CLASS__, 'profile_page_url' ) ); |
||
| 615 | } |
||
| 616 | } else wp_nonce_ays(); |
||
| 617 | } |
||
| 618 | |||
| 619 | if ( empty( $user ) ) { |
||
| 620 | $user = $this->get_user_by_wpcom_id( $user_data->ID ); |
||
| 621 | } |
||
| 622 | |||
| 623 | // If we don't have one by wpcom_user_id, try by the email? |
||
| 624 | if ( empty( $user ) && self::match_by_email() ) { |
||
| 625 | $user = get_user_by( 'email', $user_data->email ); |
||
| 626 | if ( $user ) { |
||
| 627 | update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); |
||
| 628 | } |
||
| 629 | } |
||
| 630 | |||
| 631 | // If we've still got nothing, create the user. |
||
| 632 | if ( empty( $user ) && ( get_option( 'users_can_register' ) || self::new_user_override() ) ) { |
||
| 633 | // If not matching by email we still need to verify the email does not exist |
||
| 634 | // or this blows up |
||
| 635 | /** |
||
| 636 | * If match_by_email is true, we know the email doesn't exist, as it would have |
||
| 637 | * been found in the first pass. If get_user_by( 'email' ) doesn't find the |
||
| 638 | * user, then we know that email is unused, so it's safe to add. |
||
| 639 | */ |
||
| 640 | if ( self::match_by_email() || ! get_user_by( 'email', $user_data->email ) ) { |
||
| 641 | $username = $user_data->login; |
||
| 642 | |||
| 643 | if ( username_exists( $username ) ) { |
||
| 644 | $username = $user_data->login . '_' . $user_data->ID; |
||
| 645 | } |
||
| 646 | |||
| 647 | $tries = 0; |
||
| 648 | while ( username_exists( $username ) ) { |
||
| 649 | $username = $user_data->login . '_' . $user_data->ID . '_' . mt_rand(); |
||
| 650 | if ( $tries++ >= 5 ) { |
||
| 651 | wp_die( __( "Error: Couldn't create suitable username.", 'jetpack' ) ); |
||
| 652 | } |
||
| 653 | } |
||
| 654 | |||
| 655 | $password = wp_generate_password( 20 ); |
||
| 656 | $user_id = wp_create_user( $username, $password, $user_data->email ); |
||
| 657 | $user = get_userdata( $user_id ); |
||
| 658 | |||
| 659 | $user->display_name = $user_data->display_name; |
||
| 660 | $user->first_name = $user_data->first_name; |
||
| 661 | $user->last_name = $user_data->last_name; |
||
| 662 | $user->url = $user_data->url; |
||
| 663 | $user->description = $user_data->description; |
||
| 664 | wp_update_user( $user ); |
||
| 665 | |||
| 666 | update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); |
||
| 667 | } else { |
||
| 668 | $this->user_data = $user_data; |
||
| 669 | // do_action( 'wp_login_failed', $user_data->login ); |
||
| 670 | add_action( 'login_message', array( $this, '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 WordPress.com User information. |
||
| 683 | * @param object $user_data 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 | $remember = false; |
||
| 692 | View Code Duplication | if ( ! empty( $_COOKIE['jetpack_sso_remember_me'] ) ) { |
|
| 693 | $remember = true; |
||
| 694 | // And then purge it |
||
| 695 | setcookie( 'jetpack_sso_remember_me', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 696 | } |
||
| 697 | /** |
||
| 698 | * Filter the remember me value. |
||
| 699 | * |
||
| 700 | * @module sso |
||
| 701 | * |
||
| 702 | * @since 2.8.0 |
||
| 703 | * |
||
| 704 | * @param bool $remember Is the remember me option checked? |
||
| 705 | */ |
||
| 706 | $remember = apply_filters( 'jetpack_remember_login', $remember ); |
||
| 707 | wp_set_auth_cookie( $user->ID, $remember ); |
||
| 708 | |||
| 709 | /** This filter is documented in core/src/wp-includes/user.php */ |
||
| 710 | do_action( 'wp_login', $user->user_login, $user ); |
||
| 711 | |||
| 712 | $_request_redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : ''; |
||
| 713 | $redirect_to = user_can( $user, 'edit_posts' ) ? admin_url() : self::profile_page_url(); |
||
| 714 | |||
| 715 | // If we have a saved redirect to request in a cookie |
||
| 716 | View Code Duplication | if ( ! empty( $_COOKIE['jetpack_sso_redirect_to'] ) ) { |
|
| 717 | // Set that as the requested redirect to |
||
| 718 | $redirect_to = $_request_redirect_to = esc_url_raw( $_COOKIE['jetpack_sso_redirect_to'] ); |
||
| 719 | // And then purge it |
||
| 720 | setcookie( 'jetpack_sso_redirect_to', ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); |
||
| 721 | } |
||
| 722 | |||
| 723 | wp_safe_redirect( |
||
| 724 | /** This filter is documented in core/src/wp-login.php */ |
||
| 725 | apply_filters( 'login_redirect', $redirect_to, $_request_redirect_to, $user ) |
||
| 726 | ); |
||
| 727 | exit; |
||
|
0 ignored issues
–
show
|
|||
| 728 | } |
||
| 729 | |||
| 730 | $this->user_data = $user_data; |
||
| 731 | /** This filter is documented in core/src/wp-includes/pluggable.php */ |
||
| 732 | do_action( 'wp_login_failed', $user_data->login ); |
||
| 733 | add_action( 'login_message', array( $this, 'cant_find_user' ) ); |
||
| 734 | } |
||
| 735 | |||
| 736 | static function profile_page_url() { |
||
| 737 | return admin_url( 'profile.php' ); |
||
| 738 | } |
||
| 739 | |||
| 740 | static function match_by_email() { |
||
| 741 | $match_by_email = ( 1 == get_option( 'jetpack_sso_match_by_email', true ) ) ? true: false; |
||
| 742 | $match_by_email = defined( 'WPCC_MATCH_BY_EMAIL' ) ? WPCC_MATCH_BY_EMAIL : $match_by_email; |
||
| 743 | |||
| 744 | /** |
||
| 745 | * Link the local account to an account on WordPress.com using the same email address. |
||
| 746 | * |
||
| 747 | * @module sso |
||
| 748 | * |
||
| 749 | * @since 2.6.0 |
||
| 750 | * |
||
| 751 | * @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. |
||
| 752 | */ |
||
| 753 | return apply_filters( 'jetpack_sso_match_by_email', $match_by_email ); |
||
| 754 | } |
||
| 755 | |||
| 756 | static function new_user_override() { |
||
| 757 | $new_user_override = defined( 'WPCC_NEW_USER_OVERRIDE' ) ? WPCC_NEW_USER_OVERRIDE : false; |
||
| 758 | |||
| 759 | /** |
||
| 760 | * Allow users to register on your site with a WordPress.com account, even though you disallow normal registrations. |
||
| 761 | * |
||
| 762 | * @module sso |
||
| 763 | * |
||
| 764 | * @since 2.6.0 |
||
| 765 | * |
||
| 766 | * @param bool $new_user_override Allow users to register on your site with a WordPress.com account. Default to false. |
||
| 767 | */ |
||
| 768 | return apply_filters( 'jetpack_sso_new_user_override', $new_user_override ); |
||
| 769 | } |
||
| 770 | |||
| 771 | function allowed_redirect_hosts( $hosts ) { |
||
| 772 | if ( empty( $hosts ) ) { |
||
| 773 | $hosts = array(); |
||
| 774 | } |
||
| 775 | $hosts[] = 'wordpress.com'; |
||
| 776 | |||
| 777 | return array_unique( $hosts ); |
||
| 778 | } |
||
| 779 | |||
| 780 | function button( $args = array() ) { |
||
| 781 | $defaults = array( |
||
| 782 | 'action' => 'jetpack-sso', |
||
| 783 | ); |
||
| 784 | |||
| 785 | $args = wp_parse_args( $args, $defaults ); |
||
| 786 | |||
| 787 | if ( ! empty( $_GET['redirect_to'] ) ) { |
||
| 788 | $args['redirect_to'] = esc_url_raw( $_GET['redirect_to'] ); |
||
| 789 | } |
||
| 790 | |||
| 791 | $url = add_query_arg( $args, wp_login_url() ); |
||
| 792 | |||
| 793 | $css = "<style> |
||
| 794 | .jetpack-sso.button { |
||
| 795 | position: relative; |
||
| 796 | padding-left: 37px; |
||
| 797 | } |
||
| 798 | .jetpack-sso.button:before { |
||
| 799 | display: block; |
||
| 800 | box-sizing: border-box; |
||
| 801 | padding: 7px 0 0; |
||
| 802 | text-align: center; |
||
| 803 | position: absolute; |
||
| 804 | top: -1px; |
||
| 805 | left: -1px; |
||
| 806 | border-radius: 2px 0 0 2px; |
||
| 807 | content: '\\f205'; |
||
| 808 | background: #0074a2; |
||
| 809 | color: #fff; |
||
| 810 | -webkit-font-smoothing: antialiased; |
||
| 811 | width: 30px; |
||
| 812 | height: 107%; |
||
| 813 | height: calc( 100% + 2px ); |
||
| 814 | font: normal 22px/1 Genericons !important; |
||
| 815 | text-shadow: none; |
||
| 816 | } |
||
| 817 | @media screen and (min-width: 783px) { |
||
| 818 | .jetpack-sso.button:before { |
||
| 819 | padding-top: 3px; |
||
| 820 | } |
||
| 821 | } |
||
| 822 | .jetpack-sso.button:hover { |
||
| 823 | border: 1px solid #aaa; |
||
| 824 | }"; |
||
| 825 | |||
| 826 | if ( version_compare( $GLOBALS['wp_version'], '3.8-alpha', '<' ) ) { |
||
| 827 | $css .= " |
||
| 828 | .jetpack-sso.button:before { |
||
| 829 | width: 25px; |
||
| 830 | font-size: 18px !important; |
||
| 831 | } |
||
| 832 | "; |
||
| 833 | } |
||
| 834 | |||
| 835 | $css .= "</style>"; |
||
| 836 | |||
| 837 | $button = sprintf( '<a href="%1$s" class="jetpack-sso button">%2$s</a>', esc_url( $url ), esc_html__( 'Log in with WordPress.com', 'jetpack' ) ); |
||
| 838 | return $button . $css; |
||
| 839 | } |
||
| 840 | |||
| 841 | function build_sso_url( $args = array() ) { |
||
| 842 | $defaults = array( |
||
| 843 | 'action' => 'jetpack-sso', |
||
| 844 | 'site_id' => Jetpack_Options::get_option( 'id' ), |
||
| 845 | 'sso_nonce' => self::request_initial_nonce(), |
||
| 846 | ); |
||
| 847 | |||
| 848 | if ( isset( $_GET['state'] ) && check_admin_referer( $_GET['state'] ) ) { |
||
| 849 | $defaults['state'] = rawurlencode( $_GET['state'] . '|' . $_GET['_wpnonce'] ); |
||
| 850 | } |
||
| 851 | |||
| 852 | $args = wp_parse_args( $args, $defaults ); |
||
| 853 | $url = add_query_arg( $args, 'https://wordpress.com/wp-login.php' ); |
||
| 854 | |||
| 855 | return $url; |
||
| 856 | } |
||
| 857 | |||
| 858 | /** |
||
| 859 | * Determines local user associated with a given WordPress.com user ID. |
||
| 860 | * |
||
| 861 | * @since 2.6.0 |
||
| 862 | * |
||
| 863 | * @param int $wpcom_user_id User ID from WordPress.com |
||
| 864 | * @return object Local user object if found, null if not. |
||
| 865 | */ |
||
| 866 | static function get_user_by_wpcom_id( $wpcom_user_id ) { |
||
| 867 | $user_query = new WP_User_Query( array( |
||
| 868 | 'meta_key' => 'wpcom_user_id', |
||
| 869 | 'meta_value' => intval( $wpcom_user_id ), |
||
| 870 | 'number' => 1, |
||
| 871 | ) ); |
||
| 872 | |||
| 873 | $users = $user_query->get_results(); |
||
| 874 | return $users ? array_shift( $users ) : null; |
||
| 875 | } |
||
| 876 | |||
| 877 | /** |
||
| 878 | * Error message displayed on the login form when two step is required and |
||
| 879 | * the user's account on WordPress.com does not have two step enabled. |
||
| 880 | * |
||
| 881 | * @since 2.7 |
||
| 882 | * @param string $message |
||
| 883 | * @return string |
||
| 884 | **/ |
||
| 885 | public function error_msg_enable_two_step( $message ) { |
||
| 886 | $err = __( sprintf( 'This site requires two step authentication be enabled for your user account on WordPress.com. Please visit the <a href="%1$s"> Security Settings</a> page to enable two step', 'https://wordpress.com/me/security/two-step' ) , 'jetpack' ); |
||
| 887 | |||
| 888 | $message .= sprintf( '<p class="message" id="login_error">%s</p>', $err ); |
||
| 889 | |||
| 890 | return $message; |
||
| 891 | } |
||
| 892 | |||
| 893 | /** |
||
| 894 | * Error message displayed when the user tries to SSO, but match by email |
||
| 895 | * is off and they already have an account with their email address on |
||
| 896 | * this site. |
||
| 897 | * |
||
| 898 | * @param string $message |
||
| 899 | * @return string |
||
| 900 | */ |
||
| 901 | public function error_msg_email_already_exists( $message ) { |
||
| 902 | $err = __( sprintf( 'You already have an account on this site. Please visit your <a href="%1$s">profile page</a> page to link your account to WordPress.com!', admin_url( 'profile.php' ) ) , 'jetpack' ); |
||
| 903 | |||
| 904 | $message .= sprintf( '<p class="message" id="login_error">%s</p>', $err ); |
||
| 905 | |||
| 906 | return $message; |
||
| 907 | } |
||
| 908 | |||
| 909 | /** |
||
| 910 | * Message displayed when the site admin has disabled the default WordPress |
||
| 911 | * login form in Settings > General > Single Sign On |
||
| 912 | * |
||
| 913 | * @since 2.7 |
||
| 914 | * @param string $message |
||
| 915 | * @return string |
||
| 916 | **/ |
||
| 917 | public function msg_login_by_jetpack( $message ) { |
||
| 918 | |||
| 919 | $msg = __( sprintf( 'Jetpack authenticates through WordPress.com — to log in, enter your WordPress.com username and password, or <a href="%1$s">visit WordPress.com</a> to create a free account now.', 'http://wordpress.com/signup' ) , 'jetpack' ); |
||
| 920 | |||
| 921 | /** |
||
| 922 | * Filter the message displayed when the default WordPress login form is disabled. |
||
| 923 | * |
||
| 924 | * @module sso |
||
| 925 | * |
||
| 926 | * @since 2.8.0 |
||
| 927 | * |
||
| 928 | * @param string $msg Disclaimer when default WordPress login form is disabled. |
||
| 929 | */ |
||
| 930 | $msg = apply_filters( 'jetpack_sso_disclaimer_message', $msg ); |
||
| 931 | |||
| 932 | $message .= sprintf( '<p class="message">%s</p>', $msg ); |
||
| 933 | return $message; |
||
| 934 | } |
||
| 935 | |||
| 936 | /** |
||
| 937 | * Error message displayed on the login form when the user attempts |
||
| 938 | * to post to the login form and it is disabled. |
||
| 939 | * |
||
| 940 | * @since 2.8 |
||
| 941 | * @param string $message |
||
| 942 | * @param string |
||
| 943 | **/ |
||
| 944 | public function error_msg_login_method_not_allowed( $message ) { |
||
| 945 | $err = __( 'Login method not allowed' , 'jetpack' ); |
||
| 946 | $message .= sprintf( '<p class="message" id="login_error">%s</p>', $err ); |
||
| 947 | |||
| 948 | return $message; |
||
| 949 | } |
||
| 950 | function cant_find_user( $message ) { |
||
| 951 | if ( self::match_by_email() ) { |
||
| 952 | $err_format = __( 'We couldn\'t find an account with the email <strong><code>%1$s</code></strong> to log you in with. If you already have an account on <strong>%2$s</strong>, please make sure that <strong><code>%1$s</code></strong> is configured as the email address, or that you have connected to WordPress.com on your profile page.', 'jetpack' ); |
||
| 953 | } else { |
||
| 954 | $err_format = __( 'We couldn\'t find any account on <strong>%2$s</strong> that is linked to your WordPress.com account to log you in with. If you already have an account on <strong>%2$s</strong>, please make sure that you have connected to WordPress.com on your profile page.', 'jetpack' ); |
||
| 955 | } |
||
| 956 | $err = sprintf( $err_format, $this->user_data->email, get_bloginfo( 'name' ) ); |
||
| 957 | $message .= sprintf( '<p class="message" id="login_error">%s</p>', $err ); |
||
| 958 | return $message; |
||
| 959 | } |
||
| 960 | |||
| 961 | /** |
||
| 962 | * Deal with user connections... |
||
| 963 | */ |
||
| 964 | function admin_init() { |
||
| 965 | add_action( 'show_user_profile', array( $this, 'edit_profile_fields' ) ); // For their own profile |
||
| 966 | add_action( 'edit_user_profile', array( $this, 'edit_profile_fields' ) ); // For folks editing others profiles |
||
| 967 | |||
| 968 | if ( isset( $_GET['jetpack_sso'] ) && 'purge' == $_GET['jetpack_sso'] && check_admin_referer( 'jetpack_sso_purge' ) ) { |
||
| 969 | $user = wp_get_current_user(); |
||
| 970 | // Remove the connection on the wpcom end. |
||
| 971 | self::delete_connection_for_user( $user->ID ); |
||
| 972 | // Clear it locally. |
||
| 973 | delete_user_meta( $user->ID, 'wpcom_user_id' ); |
||
| 974 | delete_user_meta( $user->ID, 'wpcom_user_data' ); |
||
| 975 | // Forward back to the profile page. |
||
| 976 | wp_safe_redirect( remove_query_arg( array( 'jetpack_sso', '_wpnonce' ) ) ); |
||
| 977 | } |
||
| 978 | } |
||
| 979 | |||
| 980 | /** |
||
| 981 | * Determines if a local user is connected to WordPress.com |
||
| 982 | * |
||
| 983 | * @since 2.8 |
||
| 984 | * @param integer $user_id - Local user id |
||
| 985 | * @return boolean |
||
| 986 | **/ |
||
| 987 | public function is_user_connected( $user_id ) { |
||
| 988 | return $this->get_user_data( $user_id ) ; |
||
| 989 | } |
||
| 990 | |||
| 991 | /** |
||
| 992 | * Retrieves a user's WordPress.com data |
||
| 993 | * |
||
| 994 | * @since 2.8 |
||
| 995 | * @param integer $user_id - Local user id |
||
| 996 | * @return mixed null or stdClass |
||
| 997 | **/ |
||
| 998 | public function get_user_data( $user_id ) { |
||
| 999 | return get_user_meta( $user_id, 'wpcom_user_data', true ); |
||
| 1000 | } |
||
| 1001 | |||
| 1002 | function edit_profile_fields( $user ) { |
||
| 1003 | wp_enqueue_style( 'genericons' ); |
||
| 1004 | ?> |
||
| 1005 | |||
| 1006 | <h3 id="single-sign-on"><?php _e( 'Single Sign On', 'jetpack' ); ?></h3> |
||
| 1007 | <p><?php _e( 'Connecting with Single Sign On enables you to log in via your WordPress.com account.', 'jetpack' ); ?></p> |
||
| 1008 | |||
| 1009 | <?php if ( $this->is_user_connected( $user->ID ) ) : /* If the user is currently connected... */ ?> |
||
| 1010 | <?php $user_data = $this->get_user_data( $user->ID ); ?> |
||
| 1011 | <table class="form-table jetpack-sso-form-table"> |
||
| 1012 | <tbody> |
||
| 1013 | <tr> |
||
| 1014 | <td> |
||
| 1015 | <div class="profile-card"> |
||
| 1016 | <?php echo get_avatar( $user_data->email ); ?> |
||
| 1017 | <p class="connected"><strong><?php _e( 'Connected', 'jetpack' ); ?></strong></p> |
||
| 1018 | <p><?php echo esc_html( $user_data->login ); ?></p> |
||
| 1019 | <span class="two_step"> |
||
| 1020 | <?php |
||
| 1021 | if( $user_data->two_step_enabled ) { |
||
| 1022 | ?> <p class="enabled"><a href="https://wordpress.com/me/security/two-step"><?php _e( 'Two-Step Authentication Enabled', 'jetpack' ); ?></a></p> <?php |
||
| 1023 | } else { |
||
| 1024 | ?> <p class="disabled"><a href="https://wordpress.com/me/security/two-step"><?php _e( 'Two-Step Authentication Disabled', 'jetpack' ); ?></a></p> <?php |
||
| 1025 | } |
||
| 1026 | ?> |
||
| 1027 | </span> |
||
| 1028 | |||
| 1029 | </div> |
||
| 1030 | <p><a class="button button-secondary" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'jetpack_sso', 'purge' ), 'jetpack_sso_purge' ) ); ?>"><?php _e( 'Unlink This Account', 'jetpack' ); ?></a></p> |
||
| 1031 | </td> |
||
| 1032 | </tr> |
||
| 1033 | </tbody> |
||
| 1034 | </table> |
||
| 1035 | |||
| 1036 | <style> |
||
| 1037 | .jetpack-sso-form-table td { |
||
| 1038 | padding-left: 0; |
||
| 1039 | } |
||
| 1040 | |||
| 1041 | .jetpack-sso-form-table .profile-card { |
||
| 1042 | padding: 10px; |
||
| 1043 | background: #fff; |
||
| 1044 | overflow: hidden; |
||
| 1045 | max-width: 400px; |
||
| 1046 | box-shadow: 0 1px 2px rgba( 0, 0, 0, 0.1 ); |
||
| 1047 | margin-bottom: 1em; |
||
| 1048 | } |
||
| 1049 | |||
| 1050 | .jetpack-sso-form-table .profile-card img { |
||
| 1051 | float: left; |
||
| 1052 | margin-right: 1em; |
||
| 1053 | width: 48px; |
||
| 1054 | height: 48px; |
||
| 1055 | } |
||
| 1056 | |||
| 1057 | .jetpack-sso-form-table .profile-card .connected { |
||
| 1058 | float: right; |
||
| 1059 | margin-right: 0.5em; |
||
| 1060 | color: #0a0; |
||
| 1061 | } |
||
| 1062 | |||
| 1063 | .jetpack-sso-form-table .profile-card p { |
||
| 1064 | margin-top: 0.7em; |
||
| 1065 | font-size: 1.2em; |
||
| 1066 | } |
||
| 1067 | |||
| 1068 | .jetpack-sso-form-table .profile-card .two_step .enabled a { |
||
| 1069 | float: right; |
||
| 1070 | color: #0a0; |
||
| 1071 | } |
||
| 1072 | |||
| 1073 | .jetpack-sso-form-table .profile-card .two_step .disabled a { |
||
| 1074 | float: right; |
||
| 1075 | color: red; |
||
| 1076 | } |
||
| 1077 | </style> |
||
| 1078 | |||
| 1079 | <?php elseif ( get_current_user_id() == $user->ID && Jetpack::is_user_connected( $user->ID ) ) : ?> |
||
| 1080 | |||
| 1081 | <?php echo $this->button( 'state=sso-link-user&_wpnonce=' . wp_create_nonce('sso-link-user') ); // update ?> |
||
| 1082 | |||
| 1083 | <?php else : ?> |
||
| 1084 | |||
| 1085 | <p><?php esc_html_e( wptexturize( __( "If you don't have a WordPress.com account yet, you can sign up for free in just a few seconds.", 'jetpack' ) ) ); ?></p> |
||
| 1086 | <a href="<?php echo Jetpack::init()->build_connect_url( false, get_edit_profile_url( get_current_user_id() ) . '#single-sign-on' ); ?>" class="button button-connector" id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a> |
||
| 1087 | |||
| 1088 | <?php endif; |
||
| 1089 | } |
||
| 1090 | } |
||
| 1091 | |||
| 1092 | Jetpack_SSO::get_instance(); |
||
| 1093 |
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.