Working With WordPress User Roles and Capabilities

WordPress user roles

There are a few things that you must understand about user roles and capabilities to be an effective administrator of a WordPress site: things like what a user is, how you make a new one, and what you’d make users for. There’s lots of value in covering those things, but our goal today is to really get a solid understanding of how the whole WordPress user management and role system works conceptually, and to cover a few of the most important ways of modifying it.

The Basics of a WordPress User

Every account that can log into a WordPress site represents a “user,” and every WordPress user has a “role.”

Every account that can log into a WordPress site represents a “user.” That is, every “login” — a username-password pair — is a unit of credentialing in WordPress. These user accounts are the authors of posts, pages, media, etc. As the administrator of a WordPress site, you can create new users at will, by going to “User > Add New” in the administration sidebar. You should, generally, create a new user for each person who you want to log in to your site.

You may also have realized something else about WordPress’s authorization system: each WordPress user has a “role.” You have to select it on the page where you create a new account.

WordPress Default User Roles

Out of the box, WordPress comes with the following roles:

  • Super Administrator: This is a multi-site-network-only role. It is, as the name suggests, a more powerful version of an Administrator. A Super Admin can not only change and control a single WordPress site as an Administrator, but can change who has access to specific sites in a network. A fancy thing to call this role would be “WordPress Multisite Keymaster.” But I can see why they went with “Super Admin” instead 🤓
  • Administrator: This is the role you probably use to log into your own WordPress site. It’s what WordPress makes the first user on a site by default, and it’s the most powerful role in the arsenal. If an “Administrator” can’t do it out of the box on a WordPress site, it can’t be done by anyone. Install plugins, change themes, make users, make posts, etc, etc.: all in the Administrator’s control.
  • Editor: This is the next most powerful role. You can do all the necessary post- and media- authoring and editing things you can imagine, but you can’t make a new user, or add a new plugin, or do anything that changes how the site functions.
  • Author: Another step down from an Editor, the Author role can only change their own posts and media. They can’t make changes to those of other users on the site.
  • Contributor: Contributors can edit their own posts, delete unpublished posts they made, and read the site. That’s it. They can’t even publish their own posts.
  • Subscriber: The Subscriber role is meant for just that: a person you want to have an account on your WordPress site, but who you don’t want able to do anything but read your site like someone without an account can. This role is what you’ll most often see given to “members” of a WordPress membership site, because it provide no site rights other than what the membership plugin author gives those uses.

The Security Implications of a WordPress User

For security, you want to provide individuals with the least possible amount of access that allows them to do what they need.

Though not our focus today, it’s worth noting a general principle of security everywhere: you want to provide individuals with the least possible amount of access that allows them to do what they need. This is as true on your WordPress site as it is for a country’s nuclear arsenal. (And you want a lot more about this topic, check out our security course, WordPress Security with Confidence.)

The user you most commonly use on your WordPress site generally shouldn’t be an administrator.

That’s why you’ll come across people giving the not-frequently-followed advice that the user you most commonly use on your WordPress site — to make edits, publish posts, make comments, etc. — generally shouldn’t be an administrator. The “Administrator” role is the most powerful that a (single, non-network) WordPress site comes with; giving that much power to a user who only needs to publish and edit articles and other media represents an unnecessary security mistake.

For normal WordPress publishing tasks, the Editor role is more than adequate; and realistically, if you’re the only writer on the site, it’s possible that the Author role would do for you. Either way, you should log into an Administrator user — which you’d also have — only when you need to do things your other role can’t: create new users, install or uninstall plugins, change themes, etc. This means that a compromise of your most-used WordPress account — say you inadvertently leave it logged in at a café — doesn’t let someone wreak complete havoc on your site.

You shouldn’t leave old accounts with more access than they need today.

Similarly, you shouldn’t just give people accounts, of any type, without some consideration. And you shouldn’t leave old accounts with more access than they need today. Say someone used to write for your site but no longer does: make them a Subscriber. Their account still exists, so their posts remain available and properly attributed, but they can’t accidentally do anything they shouldn’t be able to on your site. (Again, I’m just glossing over the whole security theory here, but WPSwC covers it in much more depth. 🤓)

How Capabilities And Roles Intertwine

Roles and Capabilities « WordPress CodexSo far, we’ve established that different user roles have different capabilities on a WordPress site. This is, in fact, the heart of WordPress’s access control system: A user is a member of the group of users assigned a specific role, and that role itself maps to a variety of capabilities on the site.

To understand this better, I used to love the giant chart on the Roles and Capabilities page on the Codex which is screenshotted at right. Unfortunately, that’s gone and the new version in the Handbook is less visually pleasing (though still as useful). As we move down the roles I listed earlier, your role will have fewer and fewer of the specific capabilities that are available in WordPress.

This mapping of concrete named capability to user roles is one of the most powerful and useful features of WordPress’s access control system. When you need to empower (or disempower) a user or set of users with specific capabilities, you can easily do so, by simply changing the role that user has.

Similarly, sometimes you’ll need all of a set of users to have a new capabilities. Perhaps your Editors are working as moderators for comments, and you’d also like them to have the ability to remove users from your site. (Maybe you’ve got some real trolls who you’d like to take out of the mix.) Then you’re able to just edit the Editor role to give it that power — and only that power, called remove_users. Because of the Roles and Capabilities system you can do that, without needing to worry about the fact that you’ve got 20 editors on your site.

Plugins that Allow You to Change a Role’s Capabilities

user-role-editor-plugin-shotOnce you understand the basics of how WordPress user access system works, that you can make a change like the one I just mentioned (give Editors the “remove users” capability) in a number of ways.

The first way is using one of a whole mess of plugins. User Role Editor is the most common, but feel free to shop around if you like others. These plugins all basically give you a convenient and visual way to edit the things that users will be able to do on your site.

They also allow you to create whole new roles — perhaps you’ve got a need to create some users who are simply and only “Comment Moderator” types. You can just create that role, and make sure you narrow down the features it needs in a few simple clicks.

These plugins are great for most WordPress users, who don’t need to sweat their modest performance overhead. Realistically, for most sites the overhead of a small plugin like this isn’t the biggest bottleneck, so the added benefit of a dedicated plugin to just make the changes you want isn’t worth sweating the PHP for.

But, if you’re a developer-type, or that performance hit is really too much to bear, it’s pretty easy to do with a few lines of PHP.

Changing Capabilities Of a WordPress User Role With PHP

In PHP, a WordPress role is an object that you use and modify.

In PHP, a WordPress role is an object that you use and modify. You can access it one of two ways: directly by accessing a global variable — $wp_roles — or through an accessor function called get_role. I like the second better for two reasons:

  1. I dislike global variables.
  2. I think the get_role version makes the code read better.

In both cases, we’ll follow on with our example of allowing our Editors to remove_users. That looks like this, if you use get_role:

function wps_editor_can_remove_users() {
    $editor = get_role( 'editor' );
    $editor->add_cap( 'remove_users' );

or, if you prefer to access a global variable:

function wps_editor_can_remove_users(){
    global $wp_roles;
    $wp_roles->add_cap( 'editor', 'remove_users' );

In the first example, the fetch of a role (‘editor’) takes care of the 'editor' parameter on the add_cap method call for you, which I like; either way works.

These methods can be called directly in your plugin or in your theme’s functions.php — the changes are stored to the database, so can be called at any time — or can be hooked to init through a WordPress action.

Both add_cap and remove_cap are object methods, and not simply functions you call.

It’s worth being very clear that both add_cap and remove_cap (its opposite) are object methods, and not simply functions you call. That is, you can’t call add_cap('editor', 'remove_user'): you must instead first get a WP_Role object, by either using get_role or by accessing the global $wp_roles object.

Creating New WordPress User Roles, Programmatically

We mentioned that plugins will let you create new roles, in addition to changing the capabilities of existing roles. To do this in your own PHP, you use the add_role function. It takes three parameters:

  1. A slug-like name for the role — say 'comment_moderator'
  2. A display name for the role — either 'Comment Moderator' or __('Commment Moderator', 'plugin-slug') if you’re worried about internationalization
  3. An array of the capabilities you want that type of user to have

In all, it looks something like this:

register_activation_hook( __FILE__, 'wps_add_roles_on_activation' );
function wps_add_roles_on_activation() {
        __('Commment Moderator', 'plugin-slug'), 
            'read' => true,
            'edit_posts' => true,
            'edit_other_posts' => true,
            'edit_published_posts' => true,
            'moderate_comments' => true

For the sake of conciseness, this role only gets four capabilities. Comment Moderators can moderate comments, and make minor changes and corrections to posts (probably in response to comments). They’re able to change their own posts, other people’s posts, and posts that have been published. That’s all this role can do, nothing else.

Again, because new roles are stored in the database and reloaded from there by WordPress when needed, you can — and generally should — have them created right when your plugin (or theme if you’re building this in a theme, which you shouldn’t) is activated. It’s doesn’t break anything if you have them hooked to the init action, but it is modestly less performant.

Changing a Specific User’s Capabilities

Ignoring WordPress’s roles system and granting user-specific capabilities is possible, but it’s very rarely the best solution.

So far, we’ve discussed using WordPress capabilities as granted by and maintained by user roles. This is what I’d recommend you do to change, control, and modify access in almost all cases. It’s a more powerful and flexible system than trying to manually control the things that each individual user on your site does.

That being said, some times you may need to just deal with a specific user who needs more or fewer powers, and you know that you’ll never want to empower (or disempower) another user similarly at any other time in the history of the site. If that’s not true, go through the few extra steps of making a role, which only this user gets for now.

If you really do want to change a specific user’s capabilities, you can do so with the add_cap and remove_cap methods on the user itself. That looks something like:

add_action( 'init', 'wps_david_cant_edit' );
function wps_david_cant_edit() {
    $user_id = 7; // The ID of the user
    $user = new WP_User( $user_id );
    $user->remove_cap( 'edit_posts' );

This essentially is a specific override on a specific user, after the role’s general capabilities have been loaded. Again, this is possible, but very likely not to be the best solution: the concerns that led you to want to give or take capabilities from a user are likely to be shared with some other user at some point, and you’d have more power with a role.

What We’ve Learned about WordPress Users

At its heart, the WordPress user system is how we deal with power over a WordPress site. By assigning each user in the system a named role, WordPress provides access to a clearly defined set of capabilities that determine what that user can do on the site. Because of this extra layer — named roles — between what users can do and what who they are, you get a ton of flexibility. It’s just another thing that makes WordPress great. Happy hacking!

Image credit: Chris Heard

Most Voted
Newest Oldest
Inline Feedbacks
View all comments
May 7, 2020 10:13 am

I have a custom user role and I want to hide a classic editor button from them. I can get their current capabilities but can’t work out what to check for to hide the buttons I don’t want them to see. Any hints?

May 8, 2020 6:37 pm
Reply to  Colin

Hey Colin, can you be more specific with what you mean by “a classic editor button.”

While this isn’t an ideal solution, you can always visually hide any element on any page by checking for a particular user role and enqueuing a custom stylesheet which will include CSS to hide the element you want hidden.

Since this will be done on the admin side, you can hook into the “admin_enqueue_scripts” action to load your custom stylesheet.