Master WordPress security by implementing capability checks. Learn to use current_user_can to restrict admin features and enforce proper access control.
Previously in this course, we covered implementing nonces to prevent Cross-Site Request Forgery. While nonces secure individual form submissions, they don't define who is allowed to perform an action. This lesson adds a critical layer of security by teaching you how to restrict access to your plugin’s administrative features using WordPress capabilities.
In WordPress, you should almost never check for a user role (like administrator or editor). Instead, you should check for a capability.
Roles are essentially buckets of capabilities. For example, the "Administrator" role has the manage_options capability, while "Editor" does not. If you hardcode a check for administrator, your plugin will break for site owners who use custom roles or plugins that modify permissions.
By checking for the capability, you ensure your plugin respects the site’s existing security configuration. This is the foundation of effective access control and authorization.
current_user_can FunctionThe primary tool for verifying permissions is current_user_can(). It accepts a capability string and returns a boolean.
PHPif ( current_user_can( 'manage_options' ) ) { #6A9955">// The user is allowed to proceed } else { #6A9955">// The user does not have permission wp_die( 'You do not have sufficient permissions to access this page.' ); }
In our Knowledge Base plugin, we have an AdminController that handles settings and management pages. We must ensure that only authorized users can trigger these methods.
Here is how to implement a secure check within your controller methods:
PHPnamespace KnowledgeBase\Controllers; class AdminController { public function render_settings_page() { #6A9955">// 1. Always perform the capability check first if ( ! current_user_can( 'manage_options' ) ) { return; #6A9955">// Or throw an error } #6A9955">// 2. Render the view include_once plugin_dir_path( __FILE__ ) . '../views/admin-settings.php'; } public function process_article_deletion( $article_id ) { #6A9955">// Use a more specific capability for content management if ( ! current_user_can( 'delete_posts' ) ) { wp_die( __( 'Unauthorized access.' ) ); } #6A9955">// Proceed with deletion logic... } }
When designing your plugin, you need to choose the capability that best fits the action:
manage_options: Use this for plugin settings and configuration pages.edit_posts: Use this for creating or editing custom content types (Knowledge Base articles).delete_posts: Use this for removing content.publish_posts: Use this if you want to restrict who can take an article from "Draft" to "Published."If you need a custom capability (e.g., manage_kb_articles), you can assign it to roles during your plugin's activation hook using get_role( 'administrator' )->add_cap( 'manage_kb_articles' ).
Modify your AdminController (from our ongoing project) to secure the main settings page.
AdminController that renders the settings page.current_user_can( 'manage_options' ) check at the very top of that method.wp_die().if ( current_user_can( 'administrator' ) ). It is a brittle pattern that fails for multisite setups or custom user roles.current_user_can() internally checks if the user is logged in, but being explicit doesn't hurt. If your action is strictly for logged-in users, consider wrapping your logic in a check for is_user_logged_in().Authorization is the gatekeeper of your plugin. By shifting from role-based checks to capability-based checks, you ensure your plugin is secure and compatible with the broader WordPress ecosystem. Always validate the user's rights before executing sensitive controller logic, and remember that current_user_can is your primary line of defense.
Up next: We will discuss how to safely manage schema changes and versioning in your plugin using dbDelta.
Learn to extend the WordPress REST API by registering custom endpoints. We'll show you how to securely serve your Knowledge Base data as structured JSON.
Capability Checks
Plugin Security Best Practices
Composer for Dependencies
Theme Integration Hooks
Managing Assets with Gulp/Webpack
Documentation Standards
Plugin Deployment Strategy
Advanced MVC: Dependency Injection
Handling Large Datasets
Error Handling and Logging