Single Sign-on for Multiple WordPress Installations

Lafayette Community Church uses a couple different WordPress installations for its website.

I set it up so that users need log in only once, and their login persists across both sites. I didn’t need to use any plugins or LDAP or third party authentication systems for this.

Here’s what you need to do to make it work for your site as well:

  • Both WordPress installations must be running on the same domain, even though they might reside in different subdirectories or different subdomains.
  • Both installations must be running on the same database but with different table prefixes.
  • If your secondary site already has users, you will need to do manual database updates, and that’s beyond the scope of this tutorial. The rest of this tutorial assumes you are okay with the fact that your secondary installation’s user table will be completely ignored and both installations will use the primary installation’s user table.
  • Change the wp-config.php file on the secondary blog to tell WordPress which table to use for users.

define('CUSTOM_USER_TABLE', 'blog1_users');         // replace blog1 with the table prefix from your
define('CUSTOM_USER_META_TABLE', 'blog1_usermeta'); // main wordpress installation
  • Change both wp-config.php files to unify the cookies across the two installations. I’ll go into more detail here.

Unifying Authentication Cookies across multiple WordPress Installations

WordPress uses two cookies to handle authentication, but there are a number of settings that need to be synchronized between installations so that WordPress can read and understand the cookies properly.

Authentication Keys

Your WordPress installations may or may not have custom authentication keys set up, but in order for this to work properly, you should have the same keys set up on each installation. In wp-config.php on BOTH sites, add these lines:


/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
define('AUTH_KEY',         'custom-hash-here');
define('SECURE_AUTH_KEY',  'custom-hash-here');
define('LOGGED_IN_KEY',    'custom-hash-here');
define('NONCE_KEY',        'custom-hash-here');
define('AUTH_SALT',        'custom-hash-here');
define('SECURE_AUTH_SALT', 'custom-hash-here');
define('LOGGED_IN_SALT',   'custom-hash-here');
define('NONCE_SALT',       'custom-hash-here');

Of course, you want to replace “custom-hash-here” with different random strings, and of course, if you already have these values set in your wp-config.php files, you need to replace what’s currently there with these so that both sites are using the same exact settings.

Cookie Settings

Hash, Domain, and Path

When WordPress uses three defined constants when creating authentication cookies for the browser: COOKIEHASH, COOKIE_DOMAIN, and COOKIEPATH.


define('COOKIEHASH', 'custom-hash-here'); //define the hash
define('COOKIE_DOMAIN', '.example.org');  //remove the leading dot if you aren't using subdomains
define('COOKIEPATH', '/');                //this must be a parent directory to all WP installations

Again, these three settings must be exactly the same across your all installations, but there are additional concerns:

The COOKIE_DOMAIN and the COOKIEPATH must be parents of both installations. That means, if your installations are on separate subdomains, the COOKIE_DOMAIN must apply to both (a leading dot before the domain name will accomplish this), and if your installations are using separate subdirectories, your COOKIEPATH must be a parent to both. To be safe, you can make it ‘/’, but you actually want your cookies to be as specific as possible, so if one blog is in example.org/wordpress/blog1 and the other blog is in example.org/wordpress/blog2, you can use /wordpress as your COOKIEPATH, or if one blog is blog1.example.org/wordpress and the other is blog2.example.org/wordpress, you should also be able to use /wordpress as your COOKIEPATH.

Site and Admin

WordPress uses two defined constants to help it look for the right cookies to see if a user has been authenticated. One of those constants is SITECOOKIEPATH and it is used by the WordPress frontend. The other is ADMIN_COOKIE_PATH and it is used by the WordPress backend.

Simply set both of them to be the same as the COOKIEPATH and you should be fine.


define('SITECOOKIEPATH', COOKIEPATH);
define('ADMIN_COOKIE_PATH', COOKIEPATH);

Conclusion

So, for completeness, here are all the settings together:

In secondary wp-config.php files:


define('CUSTOM_USER_TABLE',      'blog1_users');    // replace blog1 with the table prefix from your
define('CUSTOM_USER_META_TABLE', 'blog1_usermeta'); // main wordpress installation

In all wp-config.php files


define('AUTH_KEY',           'custom-hash-here');
define('SECURE_AUTH_KEY',    'custom-hash-here');
define('LOGGED_IN_KEY',      'custom-hash-here');
define('NONCE_KEY',          'custom-hash-here');
define('AUTH_SALT',          'custom-hash-here');
define('SECURE_AUTH_SALT',   'custom-hash-here');
define('LOGGED_IN_SALT',     'custom-hash-here');
define('NONCE_SALT',         'custom-hash-here');
define('COOKIEHASH',         'custom-hash-here');
define('COOKIE_DOMAIN',      '.example.org');
define('COOKIEPATH',         '/');
define('SITECOOKIEPATH',     COOKIEPATH);
define( 'ADMIN_COOKIE_PATH', COOKIEPATH );

Post a comment if it doesn’t work for you.