pyro
pyro

Reputation: 161

apache: basic authentication before rewrite

I have an Apache in frontend that should redirect a request via a RewriteRule.

I have to put a basic authentication before the request is redirected, so I put this in the config file:

<VirtualHost *:443>
    ServerAdmin xxxxxx
    DocumentRoot /var/www/html/
    ServerName xxxxxxx
    RewriteEngine on
    ErrorLog logs/error.log
    CustomLog logs/access_log common

    <Directory /var/www/html/>
        AuthType Basic
        AuthName "Restricted Files"
        AuthUserFile /etc/httpd/conf/tag.pwd
        Require valid-user
        RewriteRule ^/(.*) http://xxxxxx:xxx/$1   [P,L]
    </Directory>
</VirtualHost>

But it doesn't work.

Any suggestions?

UPDATE: I would expect that all requests after authentication would be redirected with the rule RewriteRule ^/(.*) xxxxxx:xxx/$1 [P,L] but this doesn't happen. Apache search the page under /var/www/html

Upvotes: 10

Views: 26900

Answers (4)

MrWhite
MrWhite

Reputation: 45829

<Directory /var/www/html/>
    AuthType Basic
    AuthName "Restricted Files"
    AuthUserFile /etc/httpd/conf/tag.pwd
    Require valid-user
    RewriteRule ^/(.*) http://xxxxxx:xxx/$1   [P,L]
</Directory>

There are 2 issues here that will prevent your RewriteRule from doing anything:

  1. You need to enable the rewrite engine inside the <Directory> container (a directory context). You've (incorrectly) enabled the rewrite engine in the outer <VirtualHost> container (a virtualhost context) - in which you don't have any mod_rewrite directives. The <VirtualHost> and <Directory> containers work in different contexts. If you don't enable the rewrite engine inside the <Directory> container then the directives will simply be ignored.

    RewriteEngine On
    
  2. When used in a directory context (<Directory> and .htaccess) the URL-path matched by the RewriteRule pattern does not start with a slash, since the directory-prefix (that ends in a slash) has been removed. So, you need to remove the slash prefix from the regex, otherwise, it will simply never match in a directory context:

    RewriteRule (.*) http://xxxxxx:xxx/$1 [P,L]
    

    (The ^ prefix on the pattern then becomes superfluous.)

Summary

Actioning the above points, this becomes:

<Directory /var/www/html/>
    AuthType Basic
    AuthName "Restricted Files"
    AuthUserFile /etc/httpd/conf/tag.pwd
    Require valid-user

    RewriteEngine On
    RewriteRule (.*) http://xxxxxx:xxx/$1 [P,L]
</Directory>

Alternatively, you move the RewriteRule directive outside of the <Directory> container and use this directly inside the <VirtualHost> container in which you've already enabled the rewrite engine.

However, in this context, the mod_rewrite directives will execute before the authorisation directives inside the <Directory> container, so you will need the additional condition that checks the REMOTE_USER via a look-ahead (ie. LA-U:REMOTE_USER), as mentioned in the other answers.

Upvotes: 0

Travis Wilson
Travis Wilson

Reputation: 979

In general, Apache does the rewrite phase before the authorization phase, which is why your code performs the rewrite without ever asking for user to authenticate.

You can get around this with the LA-U:REMOTE_USER variable. Preface your RewriteRule with a condition which looks ahead ("LA") to the authorization phase:

RewriteCond %{LA-U:REMOTE_USER} !^$
RewriteRule ^/(.*) http://xxxxxx:xxx/$1 [L]

See notes about this in http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond

As other posters point out, it's also better to take the RewriteRule directives out of the block so they are more reliable.

Upvotes: 13

h0tw1r3
h0tw1r3

Reputation: 6818

Update: Implicit directory rule ensures validation is always required before the rewrite is done. Found that different combinations of apache modules changed the behavior, thus the accepted answer may not always work.

<Location />
    AuthType Basic
    AuthName "Restricted Files"
    AuthUserFile /etc/httpd/conf/tag.pwd
    Require valid-user
</Location>

<Directory /documentroot>
    RewriteCond %{LA-U:REMOTE_USER} (.+)
    RewriteRule (.*) http://xxxxxx:xxx/$1   [P,L]
</Directory>

Upvotes: 2

pyro
pyro

Reputation: 161

I solved putting the rewrite condition and rewrite rule outside the Locatio directive:

<Location />
  AuthType Basic
  AuthName "Restricted Files"
  AuthUserFile /etc/httpd/conf/tag.pwd
  Require valid-user
</Location>
RewriteCond %{LA-U:REMOTE_USER} !^$
RewriteRule ^/(.*) http://xxxxxx:xxx/$1   [P,L]

many thanks to h0tw1r3 for the suggestion

*Keep in mind that Location directives operate on URLs, and not directories. That means that if someone creates an alias to the document root, they'll completely bypass these authentication rules. (See http://httpd.apache.org/docs/2.0/mod/core.html#location for more.)

Upvotes: 6

Related Questions