.htaccess - Exclude folder from basic auth protection

I have a website where no one is allowed to enter without entering the basic auth credentials.

However, I need the media folder to be accessible by everyone, because we are using a third party extension which creates PDF's and we can only fully test them if the media is accessible.

The media folder is at /var/www/company/pub/media.

The domain (www.example.com) points to /var/www/company/pub, so the pub folder is the entry point.

This is my .htaccess attempt (/var/www/company/.htaccess):

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/pub/
RewriteCond %{REQUEST_URI} !^/setup/
RewriteCond %{REQUEST_URI} !^/update/
RewriteCond %{REQUEST_URI} !^/dev/
RewriteRule .* /pub/$0 [L]
DirectoryIndex index.php

AuthType Basic
AuthName "Protected"
AuthUserFile "/var/www/company/.htpasswd"

# Exclude media folder from basic auth
SetEnvIf Request_URI "^/media/*" media

Order allow,deny
Require valid-user
Allow from env=media
Deny from env=!media
Satisfy any

But if I try to call http://www.example.com/media/someimage.jpg then I still get the basic auth login prompt.

Environment:

Apache 2.4.41 (Ubuntu)


Solution 1:

# Exclude media folder from basic auth
SetEnvIf Request_URI "^/media/*" media

Order allow,deny
Require valid-user
Allow from env=media
Deny from env=!media
Satisfy any

This would have worked, except the regex is wrong in the SetEnvIf directive, so the env var media is not set when requesting /media/someimage.jpg. You are missing a dot before the * quantifier, ie. ^/media/.*. However, you can just remove the trailing * altogether, ie. ^/media/, which is effectively the same (and more efficient).

The Deny from env=!media directive is superfluous.

So, the following should work:

# Exclude media folder from basic auth
SetEnvIf Request_URI "^/media/" media

Require valid-user
 
Order allow,deny
Allow from env=media
Satisfy Any

HOWEVER, this is using deprecated Apache 2.2 directives. On Apache 2.4 you can do the following instead:

# Exclude media folder from basic auth
SetEnvIf Request_URI "^/media/" media

Require valid-user
Require env media

The default container is <RequireAny> - so you don't need to include this. Although you can be explicit if you want:

<RequireAny>
    Require valid-user
    Require env media
</RequireAny>

Alternatively, you can surround the entire authorization block in an <If> expression. For example:

# Password protect everything except the "/media/" subdirectory
<If "%{REQUEST_URI} !~ m#^/media/#">
    AuthType Basic
    AuthName "Protected"
    AuthUserFile "/var/www/company/.htpasswd"
    Require valid-user
</If>

The operator !~ is a negated regular expression match.

Solution 2:

Place a .htaccess file in the media folder with AuthType None.

AuthType None
Require all granted