Sharing logins and users between multiple WordPress sites can be a great way to streamline user management and ensure that all of your sites are secure. Here are some of the best ways to do this:
1. Use a Single Sign-On (SSO) Solution:
Using a single sign-on solution like Auth0 or Okta can make it easy to manage user accounts across multiple WordPress sites. With SSO, users can log in to all of your sites with a single set of credentials, and you can manage user accounts from a single dashboard.
2. Use a WordPress Multisite Network:
WordPress Multisite is a feature that allows you to create a network of multiple WordPress sites that share a single installation of WordPress. This makes it easy to manage user accounts across multiple sites, as users can log in to all sites with the same credentials.
3. Use a WordPress User Management Plugin:
There are several WordPress plugins that make it easy to manage user accounts across multiple sites. These plugins allow you to create a single user database that can be used across multiple sites, and they also provide features like user synchronization and user role management.
4. Use a Third-Party User Management Service:
There are several third-party services that make it easy to manage user accounts across multiple sites. These services provide features like user synchronization, user role management, and single sign-on. They also make it easy to manage user accounts from a single dashboard.
Our goal is to set up two WordPress websites which will share logins and the same users. Once a user has subscribed one website, she would be able to access the other website with the same role and capabilities.
To achieve this goal, we should be able to edit WordPress configuration file and update database tables. A general understanding of WordPress architecture and database structure is essential, as well as a basic knowledge of WordPress development. No worries if you’re not a pro. Just follow this post directives and ask your questions in the comments.
Before we start coding, we need to know where WordPress user roles and capabilities are stored. So, our first step is to dive deep into database tables.
Important: The following will not work out of the box in the Kinsta environment due to the fact that we only allow one installation of WordPress for each site (unless you’re running WordPress multisite). It may be possible to get this working on our platform, but it would require some additional setup or development. We recommend discussing this with a WordPress developer.
By default, WordPress stores user-related data into three tables: {$pref}options
, {$pref}users
and {$pref}usermeta
.
- The
{$pref}options
table stores the full list of available roles and capabilities in a row whose option_key field is{$pref}user_roles
. - The
{$pref}users
table stores basic user data, like login, password, email, url, etc. - The
{$pref}usermeta
table stores user metadata.
When working on new WordPress installations, we don’t have to care about {$pref}user_roles
row in {$pref}options
table, because the corresponding option_value field has always the same value. We should consider this row just in case we’re working on existing installations where roles or capabilities have been changed.
No worries about {$pref}users
table, as well, because it stores basic user data that we won’t change when sharing users between websites.
The {$pref}usermeta
table is the only table we’re going to update to achieve our goal.
{$pref}usermeta
stores user metadata in key/value pairs. In this table five rows store the data that we have to consider.
The first row has the meta_key field set to {$pref}capabilities
, and the corresponding meta_value field is a serialized array holding the user role. The second row stores the user level (note that user levels are deprecated from WordPress 3.0). The remaining three rows concern dashboard settings we won’t dive into in this post.
User role, level and settings are specific to the WordPress installation and are identified by the same $pref
value. It is an important bit of information when our goal is to share users between websites, because we will have to duplicate these rows and change the meta_key
field accordingly.
That’s all we have to know about user tables when we aim to share logins and users between new WordPress installations. When working on existing websites, we should consider that many plugins add extra rows to {$pref}usermeta
, and we may be required to have a deeper look at database tables.
That being said about user tables, we can move a step forward. Now we have to define two specific constants into wp-config.php file.
Defining Custom User Tables – Share Logins
WordPress allows us to set custom tables instead of {$pref}users
and {$pref}usermeta
. This means that if two (or more) WordPress websites share one database, we can set the same users and usermeta tables for all of them. As a consequence, all websites which share these table will share the same users.
Note: In order to share the same users and usermeta tables, WordPress installations must share the same database.
We just need to define CUSTOM_USER_TABLE
and CUSTOM_USER_META_TABLE
into wp-config.php file, as shown in the following code:
// custom users and usermeta tables
define( 'CUSTOM_USER_TABLE', 'my_users_table' );
define( 'CUSTOM_USER_META_TABLE', 'my_usermeta_table' );
Note: On existing websites it’s mandatory to back-up WordPress installations before you make any changes to wp-config.php files and data tables
Now that we know what has to be done, it’s time to run our two WordPress installations.
Installing WordPress
For convenience, I will name the WordPress root folders first and second. first_
and second_
will be the respective table prefixes.
Now let’s run the first installation.
Note: All installations will share a single database, and we should provide each installation with a unique table prefix.
When the first WordPress website is up and running, we can edit its configuration file. Open /first/wp-config.php and add the following lines above the ‘stop editing’ comment:
$table_prefix = 'first_';
define('WP_DEBUG', true);
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
// custom users and usermeta tables
define( 'CUSTOM_USER_TABLE', $table_prefix . 'users' );
define( 'CUSTOM_USER_META_TABLE', $table_prefix . 'usermeta' );
/* That's all, stop editing! Happy blogging. */
We have enabled debug mode forcing WordPress to store error notices and warnings into debug.log file (read more about this topic in An in-depth view on how to configure WordPress).
Then, we have defined CUSTOM_USER_TABLE
and CUSTOM_USER_META_TABLE
constants to first_users
and first_usermeta
tables. This way we’re not changing WordPress default settings.
We are done with the first installation. Next we have to copy wp-config.php from the first installation folder and paste it into the root folder of the second installation. Be careful to change the $table_prefix value accordingly:
$table_prefix = 'second_';
define('WP_DEBUG', true);
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
// custom users and usermeta tables
define( 'CUSTOM_USER_TABLE', 'first_users' );
define( 'CUSTOM_USER_META_TABLE', 'first_usermeta' );
CUSTOM_USER_TABLE
and CUSTOM_USER_META_TABLE
are set to the first installation’s values: first_users
and first_usermeta
. That’s all for the first installation.
When running the second installation, we should set a non-existent email address for admin user as WordPress finds a number of existing users from first_users
table.
Log into the second installation admin panel as admin and list WordPress users. You’ll find the new admin user and all users from the first website (this allows them to share logins). At this point, users from one site won’t be able to log into the other website.
To grant users the same capabilities in both websites, we have to update {$pref}usermeta
table.
Roles and Capabilities
If you are running new WordPress installations, you have not to care about {$pref}options
table. You just need to update {$pref}usermeta
table.
In our example, when a new user is created in the first website, WordPress adds first_capabilities
and first_user_level
rows in first_usermeta table
. To give access to the second website, these rows should be duplicated, as shown in the image below:
When a new user is created in the second website, second_capabilities
and second_user_level
rows will be added to first_usermeta
table.
In order to give the same roles and caps to users across websites, first_capabilities
and first_user_level
rows should be duplicated in second_capabilities
and second_user_level
. With these two pairs of rows in the same first_usermeta
table, users would be able to access both websites with the same privileges.
To update all existing usermeta rows you may run a SQL query or update tables from phpMyAdmin. But what for users that will subscribe our websites from now on? According to WordPress Codex, we’d use a plugin or build a custom function.
And there we go!
Automatically Duplicate Caps and Levels with a Function
set_user_role
is an action hook which triggers anytime a new user is created or an existing user’s role has been edited. Thanks to this action, we can automate usermeta table updates.
So, in the main file of a plugin add the following function:
function ksu_save_role( $user_id, $role ) {
// Site 1
// Change value if needed
$prefix_1 = 'first_';
// Site 2 prefix
// Change value if needed
$prefix_2 = 'second_';
$caps = get_user_meta( $user_id, $prefix_1 . 'capabilities', true );
$level = get_user_meta( $user_id, $prefix_1 . 'user_level', true );
if ( $caps ){
update_user_meta( $user_id, $prefix_2 . 'capabilities', $caps );
}
if ( $level ){
update_user_meta( $user_id, $prefix_2 . 'user_level', $level );
}
}
add_action( 'set_user_role', 'ksu_save_role', 10, 2 );
The callback function keeps three arguments, two of which are required: $user_id
and $role
.
What the function does is quite self-explanatory. get_user_meta returns the specified user meta field value. We have called this function twice to retrieve first_capabilities
and first_user_level
fields. Then we have used these values to add second_capabilities
and second_user_level
fields to first_usermeta
table.
Upload ad activate this plugin into the first website.
To make installations work symmetrically, we just need to upload and activate the plugin in any installation, but setting the right values to prefixes. For instance, if we would activate this feature in the second website, we just have to declare the variables as follows:
$prefix_1 = 'second_';
$prefix_2 = 'first_';
So, edit and install the plugin into the second website and create a new user or change an existing user role. Then check the first website. The user roles will be exactly the same as the second website.
Summary
In this post, I’ve explained how to grant the same privileges to users across independent WordPress installations. Once registered into a website, the user will be able to access all websites sharing the same users and usermeta tables.
I’ve supposed to work with new installations. If you’re working on existing websites, you should consider that some plugins could have updated usermeta table, or even created new tables storing user related data. In this case, a more accurate analysis of the database would be appropriate.
If you have any questions about how to share logins in WordPress, or you’d like to share your experience with us, feel free to join the conversation posting your comments.
The full code of our plugin is available in this public Gist