diff options
Diffstat (limited to 'plugins/jetpack/modules/sso.php')
-rw-r--r-- | plugins/jetpack/modules/sso.php | 193 |
1 files changed, 92 insertions, 101 deletions
diff --git a/plugins/jetpack/modules/sso.php b/plugins/jetpack/modules/sso.php index 96a60858..c5f5538e 100644 --- a/plugins/jetpack/modules/sso.php +++ b/plugins/jetpack/modules/sso.php @@ -1,5 +1,6 @@ <?php +use Automattic\Jetpack\Connection\Manager as Connection_Manager; use Automattic\Jetpack\Roles; use Automattic\Jetpack\Status; use Automattic\Jetpack\Tracking; @@ -14,6 +15,7 @@ require_once( JETPACK__PLUGIN_DIR . 'modules/sso/class.jetpack-sso-notices.php' * Recommendation Order: 5 * First Introduced: 2.6 * Requires Connection: Yes + * Requires User Connection: Yes * Auto Activate: No * Module Tags: Developers * Feature: Security @@ -37,7 +39,6 @@ class Jetpack_SSO { add_action( 'login_form_logout', array( $this, 'store_wpcom_profile_cookies_on_logout' ) ); add_action( 'jetpack_unlinked_user', array( $this, 'delete_connection_for_user') ); add_action( 'wp_login', array( 'Jetpack_SSO', 'clear_cookies_after_login' ) ); - add_action( 'jetpack_jitm_received_envelopes', array( $this, 'inject_sso_jitm' ) ); // Adding this action so that on login_init, the action won't be sanitized out of the $action global. add_action( 'login_form_jetpack-sso', '__return_true' ); @@ -361,11 +362,6 @@ class Jetpack_SSO { $reauth = ! empty( $_GET['force_reauth'] ); $sso_url = $this->get_sso_url_or_die( $reauth ); - // Is this our first SSO Login. Set an option. - if ( ! Jetpack_Options::get_option( 'sso_first_login' ) ) { - Jetpack_options::update_option( 'sso_first_login', true ); - } - $tracking->record_user_event( 'sso_login_redirect_success' ); wp_safe_redirect( $sso_url ); exit; @@ -465,7 +461,17 @@ class Jetpack_SSO { ?> <div id="jetpack-sso-wrap"> - <?php if ( $display_name && $gravatar ) : ?> + <?php + /** + * Allow extension above Jetpack's SSO form. + * + * @module sso + * + * @since 8.6.0 + */ + do_action( 'jetpack_sso_login_form_above_wpcom' ); + + if ( $display_name && $gravatar ) : ?> <div id="jetpack-sso-wrap__user"> <img width="72" height="72" src="<?php echo esc_html( $gravatar ); ?>" /> @@ -492,33 +498,55 @@ class Jetpack_SSO { <?php else : ?> <p> <?php - echo esc_html( + /** + * Filter the messeage displayed below the SSO button. + * + * @module sso + * + * @since 10.3.0 + * + * @param string $sso_explanation Message displayed below the SSO button. + */ + $sso_explanation = apply_filters( + 'jetpack_sso_login_form_explanation_text', sprintf( + /* Translators: %s is the name of the site. */ __( 'You can now save time spent logging in by connecting your WordPress.com account to %s.', 'jetpack' ), esc_html( $site_name ) ) ); + echo esc_html( $sso_explanation ); ?> </p> <?php endif; ?> </div> - <?php if ( ! Jetpack_SSO_Helpers::should_hide_login_form() ) : ?> - <div class="jetpack-sso-or"> - <span><?php esc_html_e( 'Or', 'jetpack' ); ?></span> - </div> + <?php + /** + * Allow extension below Jetpack's SSO form. + * + * @module sso + * + * @since 8.6.0 + */ + do_action( 'jetpack_sso_login_form_below_wpcom' ); + + if ( ! Jetpack_SSO_Helpers::should_hide_login_form() ) : ?> + <div class="jetpack-sso-or"> + <span><?php esc_html_e( 'Or', 'jetpack' ); ?></span> + </div> + + <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '1' ) ); ?>" class="jetpack-sso-toggle wpcom"> + <?php + esc_html_e( 'Log in with username and password', 'jetpack' ) + ?> + </a> - <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '1' ) ); ?>" class="jetpack-sso-toggle wpcom"> - <?php - esc_html_e( 'Log in with username and password', 'jetpack' ) - ?> - </a> - - <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '0' ) ); ?>" class="jetpack-sso-toggle default"> - <?php - esc_html_e( 'Log in with WordPress.com', 'jetpack' ) - ?> - </a> + <a href="<?php echo esc_url( add_query_arg( 'jetpack-sso-show-default-form', '0' ) ); ?>" class="jetpack-sso-toggle default"> + <?php + esc_html_e( 'Log in with WordPress.com', 'jetpack' ) + ?> + </a> <?php endif; ?> </div> <?php @@ -621,9 +649,7 @@ class Jetpack_SSO { : false; if ( ! $nonce ) { - $xml = new Jetpack_IXR_Client( array( - 'user_id' => get_current_user_id(), - ) ); + $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.sso.requestNonce' ); if ( $xml->isError() ) { @@ -652,9 +678,7 @@ class Jetpack_SSO { $wpcom_nonce = sanitize_key( $_GET['sso_nonce'] ); $wpcom_user_id = (int) $_GET['user_id']; - $xml = new Jetpack_IXR_Client( array( - 'user_id' => get_current_user_id(), - ) ); + $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.sso.validateResult', $wpcom_nonce, $wpcom_user_id ); $user_data = $xml->isError() ? false : $xml->getResponse(); @@ -687,8 +711,10 @@ class Jetpack_SSO { 'error_message' => 'error_msg_enable_two_step' ) ); + $error = new WP_Error( 'two_step_required', __( 'You must have Two-Step Authentication enabled on your WordPress.com account.', 'jetpack' ) ); + /** This filter is documented in core/src/wp-includes/pluggable.php */ - do_action( 'wp_login_failed', $user_data->login ); + do_action( 'wp_login_failed', $user_data->login, $error ); add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_msg_enable_two_step' ) ); return; } @@ -696,8 +722,17 @@ class Jetpack_SSO { $user_found_with = ''; if ( empty( $user ) && isset( $user_data->external_user_id ) ) { $user_found_with = 'external_user_id'; - $user = get_user_by( 'id', intval( $user_data->external_user_id ) ); + $user = get_user_by( 'id', (int) $user_data->external_user_id ); if ( $user ) { + $expected_id = get_user_meta( $user->ID, 'wpcom_user_id', true ); + if ( $expected_id && $expected_id != $user_data->ID ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + $error = new WP_Error( 'expected_wpcom_user', __( 'Something got a little mixed up and an unexpected WordPress.com user logged in.', 'jetpack' ) ); + + /** This filter is documented in core/src/wp-includes/pluggable.php */ + do_action( 'wp_login_failed', $user_data->login, $error ); + add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'error_invalid_response_data' ) ); // @todo Need to have a better notice. This is only for the sake of testing the validation. + return; + } update_user_meta( $user->ID, 'wpcom_user_id', $user_data->ID ); } } @@ -758,8 +793,8 @@ class Jetpack_SSO { * * @since 2.6.0 * - * @param array $user Local User information. - * @param object $user_data WordPress.com User Login information. + * @param WP_User|false|null $user Local User information. + * @param object $user_data WordPress.com User Login information. */ do_action( 'jetpack_sso_handle_login', $user, $user_data ); @@ -788,7 +823,7 @@ class Jetpack_SSO { $json_api_auth_environment = Jetpack_SSO_Helpers::get_json_api_auth_environment(); $is_json_api_auth = ! empty( $json_api_auth_environment ); - $is_user_connected = Jetpack::is_user_connected( $user->ID ); + $is_user_connected = ( new Connection_Manager( 'jetpack' ) )->is_user_connected( $user->ID ); $roles = new Roles(); $tracking->record_user_event( 'sso_user_logged_in', array( 'user_found_with' => $user_found_with, @@ -831,8 +866,11 @@ class Jetpack_SSO { ) ); $this->user_data = $user_data; + + $error = new WP_Error( 'account_not_found', __( 'Account not found. If you already have an account, make sure you have connected to WordPress.com.', 'jetpack' ) ); + /** This filter is documented in core/src/wp-includes/pluggable.php */ - do_action( 'wp_login_failed', $user_data->login ); + do_action( 'wp_login_failed', $user_data->login, $error ); add_filter( 'login_message', array( 'Jetpack_SSO_Notices', 'cant_find_user' ) ); } @@ -854,7 +892,7 @@ class Jetpack_SSO { : 'jetpack-sso button'; return sprintf( - '<a rel="nofollow" href="%1$s" class="%2$s"><span>%3$s %4$s</span></a>', + '<a rel="nofollow" href="%1$s" class="%2$s">%3$s %4$s</a>', esc_url( $url ), $classes, '<span class="genericon genericon-wordpress"></span>', @@ -890,6 +928,11 @@ class Jetpack_SSO { * @return string The WordPress.com SSO URL. */ function get_sso_url_or_die( $reauth = false, $args = array() ) { + $custom_login_url = Jetpack_SSO_Helpers::get_custom_login_url(); + if ( $custom_login_url ) { + $args['login_url'] = rawurlencode( $custom_login_url ); + } + if ( empty( $reauth ) ) { $sso_redirect = $this->build_sso_url( $args ); } else { @@ -915,12 +958,12 @@ class Jetpack_SSO { /** * Build WordPress.com SSO URL with appropriate query parameters. * - * @param array $args Optional query parameters. - * @return string WordPress.com SSO URL + * @param array $args Optional query parameters. + * @return string WordPress.com SSO URL */ - function build_sso_url( $args = array() ) { + public function build_sso_url( $args = array() ) { $sso_nonce = ! empty( $args['sso_nonce'] ) ? $args['sso_nonce'] : self::request_initial_nonce(); - $defaults = array( + $defaults = array( 'action' => 'jetpack-sso', 'site_id' => Jetpack_Options::get_option( 'id' ), 'sso_nonce' => $sso_nonce, @@ -941,10 +984,10 @@ class Jetpack_SSO { * including the parameters necessary to force the user to reauthenticate * on WordPress.com. * - * @param array $args Optional query parameters. - * @return string WordPress.com SSO URL + * @param array $args Optional query parameters. + * @return string WordPress.com SSO URL */ - function build_reauth_and_sso_url( $args = array() ) { + public function build_reauth_and_sso_url( $args = array() ) { $sso_nonce = ! empty( $args['sso_nonce'] ) ? $args['sso_nonce'] : self::request_initial_nonce(); $redirect = $this->build_sso_url( array( 'force_auth' => '1', 'sso_nonce' => $sso_nonce ) ); @@ -981,7 +1024,7 @@ class Jetpack_SSO { static function get_user_by_wpcom_id( $wpcom_user_id ) { $user_query = new WP_User_Query( array( 'meta_key' => 'wpcom_user_id', - 'meta_value' => intval( $wpcom_user_id ), + 'meta_value' => (int) $wpcom_user_id, 'number' => 1, ) ); @@ -1016,7 +1059,11 @@ class Jetpack_SSO { /** * Return the raw connect URL with our redirect and attribute connection to SSO. + * We remove any other filters that may be turning on the in-place connection + * since we will be redirecting the user as opposed to iFraming. */ + remove_all_filters( 'jetpack_use_iframe_authorization_flow' ); + add_filter( 'jetpack_use_iframe_authorization_flow', '__return_false' ); $connect_url = Jetpack::init()->build_connect_url( true, $redirect_after_auth, 'sso' ); add_filter( 'allowed_redirect_hosts', array( 'Jetpack_SSO_Helpers', 'allowed_redirect_hosts' ) ); @@ -1029,7 +1076,7 @@ class Jetpack_SSO { * stored when the user logs out, and then deleted when the user logs in. */ function store_wpcom_profile_cookies_on_logout() { - if ( ! Jetpack::is_user_connected( get_current_user_id() ) ) { + if ( ! ( new Connection_Manager( 'jetpack' ) )->is_user_connected( get_current_user_id() ) ) { return; } @@ -1081,62 +1128,6 @@ class Jetpack_SSO { public function get_user_data( $user_id ) { return get_user_meta( $user_id, 'wpcom_user_data', true ); } - - /** - * Mark SSO as discovered when an SSO JITM is viewed. - * - * @since 6.9.0 - * - * @param array $envelopes Array of JITM messages received after API call. - * - * @return array $envelopes New array of JITM messages. May now contain only one message, about SSO. - */ - public function inject_sso_jitm( $envelopes ) { - // Bail early if that's not the first time the user uses SSO. - if ( true != Jetpack_Options::get_option( 'sso_first_login' ) ) { - return $envelopes; - } - - // Update our option to mark that SSO was discovered. - Jetpack_Options::update_option( 'sso_first_login', false ); - - return $this->prepare_sso_first_login_jitm(); - } - - /** - * Prepare JITM array for new SSO users - * - * @since 6.9.0 - * - * @return array $sso_first_login_jitm array containting one object of information about our message. - */ - private function prepare_sso_first_login_jitm() { - // Build our custom SSO JITM. - $discover_sso_message = array( - 'content' => array( - 'message' => esc_html__( "You've successfully signed in with WordPress.com Secure Sign On!", 'jetpack' ), - 'icon' => 'jetpack', - 'list' => array(), - 'description' => esc_html__( 'Interested in learning more about how Secure Sign On keeps your site safer?', 'jetpack' ), - 'classes' => '', - ), - 'CTA' => array( - 'message' => esc_html__( 'Learn More', 'jetpack' ), - 'hook' => '', - 'newWindow' => true, - 'primary' => true, - ), - 'template' => 'default', - 'ttl' => 300, - 'id' => 'sso_discover', - 'feature_class' => 'sso', - 'expires' => 3628800, - 'max_dismissal' => 1, - 'activate_module' => null, - ); - - return array( json_decode( json_encode( $discover_sso_message ) ) ); - } } Jetpack_SSO::get_instance(); |