Background

There are some cases when you want a single page on your live/production site to be accessible only to certain individuals or possibly a third party company. Please note that this is different from dev or staging site’s basic authentication requirement. Drupal doesn’t have this option right off the bat so here we will discuss some of the solutions or options we can use on our sites. The solutions we will discuss are applicable for URLs with or without a physical directory such as in Drupal views.

.htaccess basic authentication

The .htaccess basic authentication is the most basic and most commonly used for password protecting the whole site but did you know that it can also be used to password protect a single page? Provided your web server has the necessary modules and services, you can achieve this single basic authentication for your Drupal site. Now when we say single page, we mean a page that corresponds to a single URL. The most important Apache module you will need is the mod_env. Let’s see the code and discuss what it does.

AuthName "Specific Page Authentication"
AuthType Basic
AuthUserFile "C:/Users/web/.htpasswd"
AuthGroupFile /dev/null

SetEnvIf Request_URI .* not-protected
SetEnvIf Request_URI ^/protected_page_url !not-protected
SetEnvIf Request_URI ^.*/anywhere_path !not-protected

<RequireAny>
  Require env not-protected
  Require valid-user
</RequireAny>

 

This explanation will focus more on the most important lines. All the other lines are either necessary or just for further information.

 

Line 3 : AuthUserFile "C:/Users/web/.htpasswd"

This is where you declare your .htpasswd file which contains the username and password for your basic authentication. The example is using a windows path set outside of the main web directory. To know more about how to create an .htpasswd file, click here [https://httpd.apache.org/docs/2.4/programs/htpasswd.html] or you may use any htpasswd generator tool you want.

 

Line 6 : SetEnvIf Request_URI .* basic-auth

This line declares all paths or Request_URIs (.*) to have not-protected set as “TRUE”. There’s not much explanation to this line but it will be used later on in the conditions.

 

Line 7 : SetEnvIf Request_URI ^/protected_page_url !not-protected

This first line sets “/protected_page_url” to have “not-protected” set as “FALSE” by adding the exclamation symbol. The symbol before the forward slash ( ^ ) signifies that the path must be right next to the base URL or domain name.

 

E.g. 

https://mydomain.com/protected_page_url = Prompts basic authentication

https://mydomain.com/protected_page_url/trailing_url = Prompts basic authentication

https://mydomain.com/preceding_url/protected_page_url = Does not prompt basic authentication

 

Line 8 : SetEnvIf Request_URI ^.*/anywhere_path !not-protected

This line is just for additional information and is not necessary. This means having only line 5 will work. In this line we added ( .* ) between ( ^ ) and the URL we want to apply basic authentication on “/anywhere_path”. This line reads, set “not-protected” for any Request URL that includes “/anywhere_path”.

 

E.g.

 

https://mydomain.com/anywhere_path = Prompts basic authentication

https://mydomain.com/anywhere_path/trailing_url = Prompts basic authentication

https://mydomain.com/preceding_url/anywhere_path = Prompts basic authentication

 

Line 11 and 12 : 

Require env not-protected

Require valid-user

This line is where the conditions above are validated. If the Request_URI’s not-protected is set to true then it will pass the validation in the next line, else if the Request_URI is protected the validation configured above will be triggered.

 

This solution is most applicable if you have full control over the application server. But if you have minimal to no control over the infrastructure, then it may be very difficult to make this work especially with the mod_env apache module which is key to identify the URI that you want to password protect.

 

Settings.php basic authentication

If you have minimal access to infrastructure or do not have mod_env required by the .htaccess solution then you can use the settings.php based basic authentication. This solution requires php knowledge or at least basic understanding for you to be able to customize the conditions. 

if (php_sapi_name() != 'cli' && isset($_SERVER['REQUEST_URI']) && str_contains($_SERVER['REQUEST_URI'], 'your_desired_protected_url')) {
  $username = 'any_username';
  $password = 'your_securepass';

  $a = base64_decode(substr($_SERVER["REMOTE_USER"], 6));
  if ((strlen($a) == 0) || (strcasecmp($a, ":") == 0)) {
    header('WWW-Authenticate: Basic realm="Private"');
    header('HTTP/1.0 401 Unauthorized');
  }
  else {
    list($name, $pass) = explode(':', $a);
    $_SERVER['PHP_AUTH_USER'] = $name;
    $_SERVER['PHP_AUTH_PW'] = $pass;
  }

  if (!(isset($_SERVER['PHP_AUTH_USER']) && ($_SERVER['PHP_AUTH_USER'] == $username && $_SERVER['PHP_AUTH_PW'] == $password))) {
    header('WWW-Authenticate: Basic realm="This site is protected"');
    header('HTTP/1.0 401 Unauthorized');
    // Message to display when the user presses cancel.
    echo '<html><head></head><body><h1>Authentication Failed</h1></body></html>';
    exit;
  }
}

 

Line 1 : if (php_sapi_name() != 'cli' && isset($_SERVER['REQUEST_URI']) && str_contains($_SERVER['REQUEST_URI'], 'your_desired_protected_url')) {

This is the only line you will probably need to edit aside from the “Authentication Failed” html response. The “isset()“ validation checks to see if the request URL has a path, meaning it is not the base URL. And if the requested URL is not base then search for the URI or path to see if a specific string exists. If the string exists then it will go through the authentication codes inside.

 

You most likely would like to modify the portion str_contains($_SERVER['REQUEST_URI'], 'your_desired_protected_url')) according to your requirements.

 

If you have no way of accessing anything from the backend at all and your Drupal site is running and maintained through web UI then read on for a module solution.


 

Password Protected Pages Module

For those who don’t have access to either .htaccess or settings.php then the only option really is a module. This module allows you to set a specific page URL to be password protected. The only downside to this is that the authentication has its own form which most likely does not work with older third party systems. Setting up this module is fairly easy and works right off the bat. The advantage of this module is that it does not need programming knowledge to be able to make it work. 

 

  • Download and install the latest version like any other modules on your site. https://www.drupal.org/project/protected_pages
  • After the installation, navigate to /admin/config/system/protected_pages
  • Once there, you will need to click on “ + Add Protected Page ” button
  • Type-in the relative path of the page you want to apply password protection to
  • Add the password and click “Save”
  • You also need to set permission for either authorized or anonymous user to have access to the authentication form