Skip to content

Restrict wp-admin Access for Non-Staff Roles

Redirects any logged-in user without real admin-area capabilities away from wp-admin and back to the front end, while still letting AJAX and REST requests through untouched.

Difficulty
Intermediate
Reading time
~1 min
Where to add it
A small custom plugin
Last updated
WooCommerce
Compatible

The Problem

On membership sites and WooCommerce stores, every registered customer or member technically has a wp-admin login, and by default WordPress lets any logged-in user open wp-admin — most menu items are hidden by capability checks, but the result is still a confusing, half-empty dashboard shown to someone who only wanted to check an order or update their account details. Beyond the poor experience, it also needlessly exposes an entire surface area — admin-only CSS and JS, plugin admin-page behavior, potential information disclosure through admin AJAX handlers — to accounts that never had a legitimate reason to see wp-admin in the first place.

The Code

php
add_action( 'admin_init', 'devmubs_restrict_admin_access' );

function devmubs_restrict_admin_access() {
    if ( wp_doing_ajax() || defined( 'REST_REQUEST' ) ) {
        return;
    }

    if ( current_user_can( 'edit_posts' ) ) {
        return;
    }

    wp_safe_redirect( home_url( '/' ) );
    exit;
}

How It Works

`admin_init` fires on every wp-admin page load, which is why the very first check is `wp_doing_ajax() || defined( 'REST_REQUEST' )` — a large number of plugins (including WooCommerce) rely on admin-ajax.php and REST endpoints being reachable even for non-staff logged-in users, so this guard runs first and returns immediately for those request types, before any redirect logic can interfere with them. `current_user_can( 'edit_posts' )` is used as the practical threshold for "has legitimate wp-admin business": WordPress's default Subscriber role and WooCommerce's Customer role both lack this capability, while Author, Editor, and Administrator all have it, so the check cleanly separates staff-ish roles from customer-ish roles without hardcoding role names directly. Anyone who fails that check gets sent to the homepage via `wp_safe_redirect()` before wp-admin renders any further.

Where To Add This

A small custom plugin. This is server-side access logic entirely unrelated to the theme, so it belongs in a small plugin that keeps enforcing the rule regardless of which theme is active.

Warnings & Caveats

  • Choose the capability check to match your own setup — if a plugin grants `edit_posts` to a role that genuinely shouldn't have wp-admin access on your site (or withholds it from a support-staff role that should), adjust the capability accordingly and test with every role you actually use before relying on this.
  • Always back up your site before adding custom code.

We use cookies

We use essential cookies to run this site, and optional cookies to understand usage and remember your preferences. Read our Cookie Policy to learn more.