sitepress = $sitepress;
$this->site_url = $this->sitepress->convert_url( $this->sitepress->get_wp_api()->get_home_url(), $this->sitepress->get_default_language() );
$this->domains = $this->get_domains();
}
public function init_hooks() {
// Add iframe
add_action( 'wp_footer', array( $this, 'add_to_footer' ) );
add_action( 'admin_footer', array( $this, 'add_to_footer' ) );
add_action( 'login_footer', array( $this, 'add_to_footer' ) );
add_action( 'init', array( $this, 'create_iframe_content' ) );
// Enqueue scripts
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_sso_script' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_sso_script' ) );
add_action( 'login_enqueue_scripts', array( $this, 'enqueue_sso_script' ) );
// Add AJAX actions
add_action( 'wp_ajax_wpml_sign_in_user', array( $this, 'sign_in_user' ) );
add_action( 'wp_ajax_nopriv_wpml_sign_in_user', array( $this, 'sign_in_user' ) );
add_action( 'wp_ajax_wpml_sign_out_user', array( $this, 'sign_out_user' ) );
add_action( 'wp_ajax_nopriv_wpml_sign_out_user', array( $this, 'sign_out_user' ) );
// Add and remove hash keys.
add_action( 'wp_login', array( $this, 'store_hash_key_in_db' ) );
add_action( 'wp_logout', array( $this, 'store_hash_key_in_db' ) );
add_action( 'wpml_delete_sso_logged_in_time_option', array( $this, 'wpml_delete_sso_logged_in_time_option' ) );
}
/**
* Delete expired key for SSO.
*/
public function wpml_delete_sso_logged_in_time_option() {
$this->remove_hash_key_from_db();
delete_option( 'wpml_sso_logged_in_time' );
}
/**
* Add content of iframe.
* This function is hooked very early and exits to avoid loadind all sites.
*/
public function create_iframe_content() {
if ( $this->should_add_content_to_iframe() ) {
$nonce = wp_create_nonce( self::WPML_LANGUAGE_PER_DOMAIN_SSO_NONCE_ACTION );
?>
domains as $domain ) {
$nonce = $this->get_url_hash( $domain );
if ( $nonce !== $this->get_url_hash() && get_option( 'wpml_sso_logged_in_time' ) ) {
?>
admin_url( 'admin-ajax.php' ),
'is_user_logged_in' => is_user_logged_in(),
'current_user_id' => get_current_user_id(),
'nonce' => $nonce,
'is_expired' => ! get_option( 'wpml_sso_logged_in_time' ),
)
);
}
/**
* Handle AJAX request and sign in user only if key in DB is present.
*/
public function sign_in_user() {
$user_id = isset( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : false;
$url_hash = $this->get_url_hash();
$sso_nonce_from_origin = get_option( $url_hash );
if ( $user_id
&& $sso_nonce_from_origin
&& $this->is_valid_ajax()
&& ! is_user_logged_in()
&& $sso_nonce_from_origin === $url_hash ) {
wp_set_auth_cookie( $user_id );
}
$this->schedule_cron();
}
/**
* Handle AJAX sign out.
*/
public function sign_out_user() {
if ( $this->is_valid_ajax() && is_user_logged_in() ) {
wp_clear_auth_cookie();
}
$this->schedule_cron();
}
/**
* Clear our hash key from db
*/
public function remove_hash_key_from_db() {
foreach ( $this->domains as $domain ) {
delete_option( $this->get_url_hash( $domain ) );
}
}
/**
* Store specific key to DB, to check later in other domains.
*/
public function store_hash_key_in_db() {
$this->wpml_delete_sso_logged_in_time_option();
update_option( 'wpml_sso_logged_in_time', time(), false );
foreach ( $this->domains as $domain ) {
$hash_url = $this->get_url_hash( $domain );
update_option( $hash_url, $hash_url, false );
}
}
/**
* Create URL hash.
*
* @param null $url
*
* @return string
*/
private function get_url_hash( $url = null ) {
if ( ! $url ) {
$protocol = 'http://';
$host = '';
if ( is_ssl() ) {
$protocol = 'https://';
}
if ( array_key_exists( 'HTTP_HOST', $_SERVER ) ) {
$host = (string) $_SERVER['HTTP_HOST'];
}
$url = $protocol . $host;
}
return hash( 'sha256', self::WPML_LANGUAGE_PER_DOMAIN_SSO_NONCE_ACTION . $url . get_option( 'wpml_sso_logged_in_time' ) );
}
/**
* @return array
*/
private function get_domains() {
$domains = $this->sitepress->get_setting( 'language_domains', array() );
$scheme = 'http://';
if ( is_ssl() ) {
$scheme = 'https://';
}
foreach ( $domains as &$domain ) {
$domain = $scheme . $domain;
}
$domains[] = $this->site_url;
return $domains;
}
private function is_valid_ajax() {
return $this->sitepress->get_wp_api()->is_ajax()
&& isset( $_POST['nonce'] )
&& wp_verify_nonce( $_POST['nonce'], self::WPML_LANGUAGE_PER_DOMAIN_SSO_NONCE_ACTION );
}
private function should_add_content_to_iframe() {
return isset( $_GET['gen_iframe'], $_GET['_wpml_gen_iframe_nonce'] )
&& $_GET['gen_iframe']
&& ! $this->is_valid_ajax()
&& $this->get_url_hash() === $_GET['_wpml_gen_iframe_nonce'];
}
private function schedule_cron() {
if ( wp_next_scheduled( 'wpml_delete_sso_logged_in_time_option' ) ) {
wp_clear_scheduled_hook( 'wpml_delete_sso_logged_in_time_option' );
}
wp_schedule_single_event( time() + self::WPML_LANGUAGE_PER_DOMAIN_SSO_TIMEOUT, 'wpml_delete_sso_logged_in_time_option' );
}
}