Paulund
2016-04-29 #wordpress

Restrict Access To WordPress Login Page

In this tutorial we're going to create a WordPress plugin that can be used to help improve the security of your site by restricting access to the login page by a querystring password override. With the WordPress login page being the entry input to the backend of your site it's important to make sure only certain people can access it.

By restricting who can access it you will cut down on brute force attacks on your login form to try to gain access. This plugin started off just by restricting by IP address but not everyone has a static IP or writers might travel around so they're always in a different location, therefore this plugin needed another way of overriding access to the login form if the IP address was different and this is done by a querystring password.

To do this we're going to make a WordPress plugin which will do a check for the querystring on the load of the login page, we then check this value against the one the admin user has entered to protect their login page.

Create The Plugin

First we create a new plugin by creating a new file in the plugins folder. Inside this file we're going to load the admin settings page if the user is currently in the admin area. This settings page is where the admin user will enter their passcode to unlock the login form. We also need to load the check for the querystring on the login form, this will go in it's own class within the plugin.

<?php
namespace Paulund_Restrict_Login_Form_Access;

use Paulund_Restrict_Login_Form_Access\Admin\Restrict_Login_Form_Settings_Page;
use Paulund_Restrict_Login_Form_Access\Login_Form\Restrict_Login_Form;

/**
 * Plugin Name:       Paulund Restrict Login Form
 * Plugin URI:        https://paulund.co.uk
 * Description:       Plugin to handle access to the login form via a querystring
 * Version:           1.0.0
 * Author:            Paulund
 * Author URI:        http://paulund.co.uk
 * Text Domain:       paulund
 */
/**
 * WordPress plugin to restrict access to the login form by querystring password
 */
class Paulund_restrict_Login_Form_Access
{
    public function __construct()
    {
        $this->loadDependencies();
    }

    private function loadDependencies()
    {
        if(is_admin())
        {
            new Restrict_Login_Form_Settings_Page();
        }

        new Restrict_Login_Form();
    }
}
new Paulund_restrict_Login_Form_Access();

Create The Admin Settings Page

We need to create a page in the admin area where the admin user can log in and set a passcode so that they can lock the login page. There are two ways we can create a settings page to add a textbox for the passcode, we can either use the Settings API or simply add a textbox to a page and set the option manually. Below is the full code to create the admin page we're not going to use the settings API as we only need one field for the page so we can create the field and the validation ourself. To start off in the constructor of the class we attach a method to the admin_menu action to add a new menu item to the settings sub menu.

add_action('admin_menu', array($this, 'add_options_menu'));

Inside the add_options_menu method we can use the function add_options_page to add a new sub menu to the settings menu.


public function add_options_menu()
{
    add_options_page(
        'Restrict Login Form Access',
        'Restrict Login Form Access',
        'manage_options',
        'restrict-login-form-access',
        array($this, 'add_settings_page')
    );
}

The callback of this menu item will display a page with a textbox so that the admin user can set a new password for the login form. You'll notice in the code below we're using the get_option() function to get the passcode we set in the database. Then on the $_POST event of the form we set this same option with the value the user entered in the form.

public function add_settings_page()
    {
        if(!empty($_POST['restrict-login-form-passcode']))
        {
            update_option('paulund-login-form-passcode', sanitize_text_field($_POST['restrict-login-form-passcode']));
        }

        $loginFormPasscode = get_option('paulund-login-form-passcode');

        if(empty($loginFormPasscode))
        {
            $loginFormPasscode = Restrict_Login_Form::defaultQuerystring;
        }
        ?>
        <div id="wrap" class="restrict-login-form-access-settings">
            <h1>Restrict Login Form Access</h1>

            <form method="post" enctype="multipart/form-data" action="">
                <table>
                    <tr>
                        <td>Passcode</td>
                        <td><input type="text" name="restrict-login-form-passcode" value="<?php echo $loginFormPasscode; ?>" /></td>
                    </tr>
                </table>

                <p class="submit">
                    <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
                </p>
            </form>
        </div>
        &lt;?php
    }

Restrict Access To The Login Form

With the passcode saved in the database we can now write the class to check this value in the database against the query string parameter to check that they're the same. If they're not the same then we can simply block access to the page by using the wp_die() function. We need to check the querystring on the load of the login page which can be done by using the login_init action.

&lt;?php
namespace Paulund_Restrict_Login_Form_Access\Login_Form;

/**
 * Restrict access to the login form
 */
class Restrict_Login_Form
{
    /**
     * Restrict_Login_Form constructor.
     */
    public function __construct()
    {
        add_action('login_init', array($this, 'check_querystring'));
    }

    /**
     * Check the querystring and allow access if the user has the correct passcode
     * @return bool
     */
    public function check_querystring()
    {
        $loginFormPasscode = get_option('paulund-login-form-passcode');

        if (empty($loginFormPasscode))
        {
            return true;
        }

        if(!empty($_GET['login-access']))
        {
            if(!empty($loginFormPasscode) && $_GET['login-access'] == $loginFormPasscode)
            {
                return true;
            }
        }

        wp_die('You do not have access to the login form');
    }
}

To improve this plugin and make sure because can't try to hack your querystring you could even add another option on the settings form to set the name of the querystring we're using instead of login-access. If you add this to the settings form then you just need to get_option on the querystring value and check this in the Restrict_Login_Form class. Now this plugin is active we can only access the login page if you you go to the URL.


/wp-login.php?login-access={passcode}

Anything else will display the you do not have access to the login form error page.