How to share cookies and sessions between domain and subdomain?

I have missed a lot of time by searching answer to my question. For today I have two WP installations on the one server and one DB but with different prefix. I already shared users data and meta between two blogs and it working fine! But I still can’t setup autologin or single sign on under two blogs. The code below does not work in WP3.8.

define('COOKIE_DOMAIN', '.domain.com'); //replace with the 1st website URL
define('COOKIEPATH', "https://wordpress.stackexchange.com/"); 

1
1

I’ll skip steps related to sharing DB and sharing users data and meta, based on assumption that you’ve done it correctly.

Let’s concentrate on wp-config.php of both sites. These are defines that MUST BE IDENTICAL for both sites:

define('COOKIE_DOMAIN', '.domain.com'); // your main domain
define('COOKIEPATH', "https://wordpress.stackexchange.com/");
define('COOKIEHASH', md5('domain.com')); // notice absence of a '.' in front

and

generated once only, KEYs and SALTs, copied to wp-config.php of both sites.

Now, if you login as any user on one site, you will be logged in, as the same user on the second site.

But wait. What happens, when you create a new user on one site, login as just created user on the same site, and try to access /wp-admin/ of the second site? You can expect to see the following message:

Sorry, you are not allowed to access this page.

This is because, on the second site, the newly created user does not have any role assigned, yet.

How to avoid user not being synchronized on both sites, in case of user’s creation or change to user’s profile?

I wrote a plugin, which should be placed in /wp-content/mu-plugins of both sites. Let’s make a new file fpw-sync-users.php, with the following code in it:

<?php
// Users synchronization
function fpw_synchronize_admins_on_admin_login( $user_login, $user ) {
    if ( array_key_exists( 'administrator', $user->caps ) ) {
        global $wpdb;
        $site_prefix = $wpdb->prefix;
        $admins_only = true;

        $other_prefixes = array(
            'wp_',
        );

        $args = array( 
            'fields'    => 'ID',
        );
        if ( $admins_only )
            $args[ 'role' ] = 'administrator';

        $users = get_users( $args );

        foreach ( $users as $id ) {
            $cap = get_user_meta( $id, $site_prefix . 'capabilities', true );

            foreach ( $other_prefixes as $prefix )
                update_user_meta( $id, $prefix . 'capabilities', $cap );
        }
    }
}
add_action( 'wp_login', 'fpw_synchronize_admins_on_admin_login', 10, 2 );

function fpw_synchronize_user_on_admin_register( $id ) {
    $me = wp_get_current_user();
    if ( array_key_exists( 'administrator', $me->caps ) ) {
        $other_prefixes = array(
            'wp_',
        );
        $user = get_user_by( 'id', $id );
        $cap = $user->caps;
        foreach ( $other_prefixes as $prefix )
            update_user_meta( $id, $prefix . 'capabilities', $cap );
    }
}
add_action( 'user_register', 'fpw_synchronize_user_on_admin_register', 10, 1 );

function fpw_synchronize_user_on_profile_update( $user_id ) {
    if ( current_user_can( 'edit_user', $user_id ) ) {
        $other_prefixes = array(
            'wp_',
        );
        $cap = array( $_POST[ 'role' ] => true, );
        foreach ( $other_prefixes as $prefix )
            update_user_meta( $user_id, $prefix . 'capabilities', $cap );
    }
 }
add_action('edit_user_profile_update', 'fpw_synchronize_user_on_profile_update');

and copy it to both destinations.

Now, edit the plugin of the first site, by replacing ‘wp_’ with real table prefix of the second site, in all three $other_prefixes arrays. Edit second site’s plugin, using real table prefix of the first site, as a replacement.

From now on, users on both sites will be fully synchronized, and login on one site will make this user, logged in on both sites.

Leave a Comment