htaccess Pass Protect Interfereing With WordPress functionality

My host asked me to implement htaccess authentication to add an extra layer of security to my WordPress installation.

When accessing the WordPress admin area I am asked for a second (server) level of authentication. This is fine, however I have a page on my site that is pass protected. Unfortunately all users of this page are also being asked for the htaccess credentials.

Read More

Is there a better way to add this brute force protection? Or perhaps a way to exclude a specific page from requiring the second factor authentication?

Also, will the latter weaken and defeat the purpose of having the second login?

Here is the relevant code from the tutorial…


ErrorDocument 401 "Unauthorized Access"
ErrorDocument 403 "Forbidden"
<FilesMatch "wp-login.php">
AuthName "Authorized Only"
AuthType Basic
AuthUserFile /home/username/.wpadmin
require valid-user
</FilesMatch>

Edit: Also this method doesn’t seem viable for WP sites that have subscribers. Surely they would need to access wp-login.php.

Related posts

Leave a Reply

4 comments

  1. Should work if you use the following directives:

    # passwordprotect wp-login.php
    <Files wp-login.php>
    <If "%{QUERY_STRING} != 'action=postpass'">
        AuthUserFile /path/to/passwd/file/.htpasswd
        AuthGroupFile /dev/null
        AuthName 'Login Message'
        AuthType Basic
        Require valid-user
    </If>
    </Files>
    
    

    What it does is, skipping the basic auth everytime the “action” string is provided and is “postpass”.

    … just a thought:

    I need to test it further myself, because i don’t know how it will affect the internal routing of WordPress e.g. /action/postpass/.

  2. Why change the htaccess when you can change the WordPress password form. Here is something that worked for me.

    add_filter( 'the_password_form', 'wpsight_password_form_dmd' );
    function wpsight_password_form_dmd($output){
        global $wp;
        $post   = get_post( $post );
        $label  = 'pwbox-' . ( empty( $post->ID ) ? rand() : $post->ID );
        $output = '<form action="' . esc_url( home_url( $wp->request ).'/?postpassnew123=1' ) . '" class="post-password-form" method="post">
        <p>' . __( 'This content is password protected. To view it please enter your password below:' ) . '</p>
        <p><label for="' . $label . '">' . __( 'Password:' ) . ' <input name="post_password" id="' . $label . '" type="password" size="20" /></label> <input type="submit" name="Submit" value="' . esc_attr_x( 'Enter', 'post password form' ) . '" /></p></form>
        ';
    return $output;    
    }
    if(isset($_GET['postpassnew123'])){
        if ( !isset($_POST['post_password'] ) ) {
            wp_safe_redirect( wp_get_referer() );
            exit();
        }
        require_once ABSPATH . WPINC . '/class-phpass.php';
        $hasher = new PasswordHash( 8, true );
    
        $expire  = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS );
        $referer = wp_get_referer();
        if ( $referer ) {
            $secure = ( 'https' === parse_url( $referer, PHP_URL_SCHEME ) );
        } else {
            $secure = false;
        }
        setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
    
        wp_safe_redirect( wp_get_referer() );
        exit();
    }
    
  3. You can exclude the page using a environment variable that matches against the requested URI:

    ErrorDocument 401 "Unauthorized Access" 
    ErrorDocument 403 "Forbidden" 
    
    SetEnvIfNoCase Request_URI ^/path/to/no-protect-page$ ok_uri=true
    
    AuthName "Authorized Only" 
    AuthType Basic 
    AuthUserFile /home/username/.wpadmin 
    Require valid-user
    Allow from env=ok_uri
    Satisfy Any
    

    So the directory where this htaccess file is placed will be password protected, except for requests to /path/to/no-protect-page.