api = $api; /** * Excluded plugin classes. * * @var array */ $this->excluded_classes = (array) apply_filters( 'wpaas_gd_login_enqueue_scripts_plugin_classes', array( 'Limit_Login_Attempts', 'Wpsec\twofa\Core\TwoFactorAuthCore', 'Wpsec\captcha\handlers\LoginFormEventHandler', ) ); /** * We must + 1 the minimum integer when hooking into SSO to ensure * that the Log class captures these events properly. * * Note: In WordPress 4.7 the SORT_NUMERIC flag was added to ksort() * for sorting filter priorities. There is also a bug in PHP 5 that * treats ~PHP_INT_MAX as greater than -PHP_INT_MAX. For this reason, * ~PHP_INT_MAX should never be used as a filter priority in WP. * * Note: Must hook into setup_theme for customize.php to work. * * @link https://gist.github.com/fjarrett/d2d1d60930d2ca4e67d35cf672ac9b13 */ add_action( 'setup_theme', [ $this, 'init' ], -PHP_INT_MAX + 1 ); add_action( 'login_init', [ $this, 'login_init' ], PHP_INT_MAX ); add_action( 'shake_error_codes', [ $this, 'shake_error_codes' ] ); add_filter( 'wp_login_errors', [ $this, 'wp_login_errors' ] ); } /** * Initialize script. * * @action setup_theme */ public function init() { // @codingStandardsIgnoreStart $action = ! empty( $_REQUEST['GD_COMMAND'] ) ? strtolower( $_REQUEST['GD_COMMAND'] ) : filter_input( INPUT_GET, 'wpaas_action' ); // Backward compat. $hash = ! empty( $_REQUEST['SSO_HASH'] ) ? $_REQUEST['SSO_HASH'] : filter_input( INPUT_GET, 'wpaas_sso_hash' ); // Backward compat. // @codingStandardsIgnoreEnd if ( 'sso_login' !== $action || ! $hash ) { return; } $uri = sanitize_url( filter_input( INPUT_SERVER, 'REQUEST_URI' ) ); $redirect = remove_query_arg( [ 'GD_COMMAND', 'SSO_HASH', 'wpaas_action', 'wpaas_sso_hash', 'nocache' ], home_url( $uri ) ); $redirect = preg_match( '~^/wp-login\.php~', $uri ) ? admin_url() : $redirect; // Go theme users should go straight to the Colors panel. if ( urldecode( $redirect ) === admin_url( 'customize.php' ) && 'go' === get_option( 'stylesheet' ) ) { $redirect = admin_url( 'customize.php?autofocus[section]=colors' ); } if ( is_user_logged_in() ) { wp_safe_redirect( esc_url_raw( $redirect ) ); exit; } $user_id = $this->user_id(); if ( is_int( $user_id ) ) { if ( $hash && $this->api->is_valid_sso_hash( $hash ) ) { @wp_set_auth_cookie( $user_id ); // @codingStandardsIgnoreLine /** Logg user action */ $GLOBALS['wpaas_activity_logger']->log_sp_action($user_id, 'SSO login success' ); wp_safe_redirect( esc_url_raw( $redirect ) ); exit; } $GLOBALS['wpaas_activity_logger']->log_sp_action($user_id, sprintf('SSO invalid hash: %s user_id: %d', $hash, $user_id) ); } /** Logg user action */ $GLOBALS['wpaas_activity_logger']->log_sp_action($user_id, 'SSO login fail' ); wp_safe_redirect( add_query_arg( static::INVALID_SSO_QARG, '', wp_login_url( admin_url() ) ) ); exit; } /** * Initialize the GD SSO login button. * * @action login_init */ public function login_init() { /** * Filter to forcefully disable the SSO login functionality. * * @var bool */ $enabled = (bool) apply_filters( 'wpaas_gd_sso_button_enabled', true ); // Only show if all conditions are met. Bail if any other plugin is customizing the login form. if ( ! $enabled || ! Plugin::is_gd() || ! defined( 'GD_ACCOUNT_UID' ) || ! GD_ACCOUNT_UID || ( isset( $_GET['wpaas-standard-login'] ) && (bool) $_GET['wpaas-standard-login'] ) || $this->is_plugin_hooked( 'login_form' ) || $this->is_plugin_hooked( 'login_enqueue_scripts' ) ) { return; } // Add a body class for our SSO login form styles. add_filter( 'login_body_class', function ( $classes ) { $classes[] = 'wpaas-show-sso-login'; return $classes; } ); add_action( 'login_head', [ $this, 'login_head' ] ); add_action( 'login_form', [ $this, 'login_form' ] ); add_action( 'login_footer', [ $this, 'login_footer' ] ); add_action( 'login_enqueue_scripts', [ $this, 'login_enqueue_scripts' ] ); } /** * Determine if a plugin is hooked into 'login_enqueue_scripts' and customizing the login screen. * * @param string $action The action to check against. * * @return boolean True when a plugin is hooked into $action, else false. */ private function is_plugin_hooked( $action ) { global $wp_filter; if ( empty( $action ) || ! array_key_exists( $action, $wp_filter ) ) { return false; } $hooked_actions = array(); $data = $wp_filter[ $action ]->callbacks[ key( $wp_filter[ $action ]->callbacks ) ]; foreach ( $data as $info ) { // Standard function. if ( is_string( $info['function'] ) ) { $hooked_actions[] = $info['function']; continue; } // Closure. if ( is_object( $info['function'] ) ) { $hooked_actions[] = get_class( $info['function'] ); continue; } // Class method. if ( is_array( $info['function'] ) ) { foreach ( $info['function'] as $hook ) { if ( is_object( $hook ) ) { $hooked_actions[] = get_class( $hook ); } } } } if ( ! empty( $hooked_actions ) ) { $hooked_actions = array_diff( $hooked_actions, $this->excluded_classes ); } return ! empty( array_filter( $hooked_actions ) ); } /** * Load fonts for SSO login button. * * @action login_head */ public function login_head() { ?>
ID ) ) ? false : $user->ID; } /** * Add our custom error message to the shaking messages * * @action shake_error_codes * @param $shake_error_codes * * @return array */ public function shake_error_codes( $shake_error_codes ) { $shake_error_codes[] = static::INVALID_SSO_QARG; return $shake_error_codes; } /** * Check if there were any SSO problems. * * @filter wp_login_errors * @param $errors * * @return mixed */ public function wp_login_errors( $errors ) { if ( ! isset( $_GET[ static::INVALID_SSO_QARG ] ) ) { // @codingStandardsIgnoreLine return $errors; } $errors->add( static::INVALID_SSO_QARG, __( 'We were unable to log you in automatically. Please enter your WordPress username and password.', 'gd-system-plugin' ), 'error' ); return $errors; } }