Skip to content

Restrict wp-login.php Behind a Secret Key

Blocks direct access to wp-login.php unless a secret query parameter is present, so automated bots hitting the default login URL get redirected instead of a login form.

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

The Problem

Every WordPress site has its login form at the same predictable path, /wp-login.php, which means automated bots don't need to discover anything about your specific site before starting a brute-force run — they already know exactly where to send requests. Renaming or fully hiding wp-login.php isn't realistically possible without a dedicated plugin, since core and many other plugins reference that filename directly. What is possible with a simple snippet is gating access to it: requiring a secret value in the URL before WordPress will even render the login form, so generic bots requesting the well-known path get turned away before authentication is ever attempted, while you access it via a URL only you know.

The Code

php
add_action( 'init', 'devmubs_guard_login_page' );

function devmubs_guard_login_page() {
    $is_login_request = isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'];

    if ( ! $is_login_request ) {
        return;
    }

    $secret_key = 'change-this-to-your-own-secret'; // Set your own value.

    if ( ! isset( $_GET['key'] ) || ! hash_equals( $secret_key, (string) $_GET['key'] ) ) {
        wp_safe_redirect( home_url( '/' ) );
        exit;
    }
}

How It Works

This runs on the `init` hook, which fires on every request, so the first thing the callback does is check `$GLOBALS['pagenow']` — a global WordPress sets to the current PHP file's basename — to confirm the request is actually for wp-login.php before doing anything else, so every other page on the site loads completely unaffected. If it is a login request, it checks for a `key` query parameter and compares it against your secret value using `hash_equals()`, which is a timing-attack-safe string comparison (a plain `===` comparison can theoretically leak information about how much of the string matched via response-time differences; `hash_equals()` avoids that). If the key is missing or wrong, `wp_safe_redirect()` sends the visitor to your homepage instead of showing a login form — a bot blindly requesting /wp-login.php with no key gets bounced immediately, before WordPress does any password checking at all.

Where To Add This

A small custom plugin. This isn't tied to your theme's presentation at all, and you'll want it to keep working across theme changes, so a small always-active plugin is the right home for it rather than functions.php.

Warnings & Caveats

  • This is obscurity, not real access control — it stops generic, script-driven bots that only know the default URL, but does nothing against a targeted attacker who already knows or guesses your key.
  • Anywhere your site links to wp-login.php directly (a theme's "Log In" link, a plugin's account menu, etc.) will break unless you update those links to include ?key=your-secret too, or additionally filter `login_url` to append it automatically.
  • Bookmark your own login URL with the key included before you save this — locking yourself out of your own site is the most common mistake with this snippet.
  • 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.