Can an htpasswd apply to all URLs except one? - apache

I have an htaccess setup for my domain, but I want one specific URL to not have htpasswd protection. That URL is a rewritten URL and doesn't have an actual directory associated with it.
Is there a way to use the root htaccess to htpasswd protect the entire site except for that one specific URL?
Edit (my code, including Jon Lin's suggestion, which isn't working for me):
RewriteCond %{SERVER_NAME} =subdomain.example.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
SetEnvIf Request_URI "^/messenger/parse" NOPASSWD=true
AuthUserFile /xxx/xxx/xxx/xxxxxx/subdomain.example.com/.htpasswd
AuthName "Staging Server"
AuthType Basic
Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=NOPASSWD

You can setup something like SetEnvIf to set an environment variable for a given Request URI. Then in the auth definition, you can use the Satisfy Any and Allow from env directives to tell apache that access can be granted either by authentication or if the environment variable exists (which is only set for a specific URI). Example:
# set the NOPASSWD variable if the request is for a specific URI
SetEnvIf Request_URI "^/specific/uri/nopasswd/$" NOPASSWD=true
# Auth directives
AuthUserFile /var/www/htpasswd
AuthName "Password Protected"
AuthType Basic
Order Deny,Allow
# Any requirment satisfies
Satisfy any
# Deny all requests
Deny from all
# except if user is authenticated
Require valid-user
# or if NOPASSWD is set
Allow from env=NOPASSWD

Related

How to bypass htpasswd auth on a specific route

mi site has apache authorization but I need to allow access to a certain url request. This url request does not represent an existing file or directory.
This is my .htaccess:
First i tried this approach:
AuthName "Required login"
AuthType Basic
AuthUserFile C:\path\to\apache\.htpasswd
Require expr %{REQUEST_URI} =~ ^specialUrl$
Require valid-user
This gives me an internal server error 500
I've tried:
%{REQUEST_URI} == ^specialUrl$
"%{REQUEST_URI} =~ ^specialUrl$"
I'm not sure how the expression is supposed to be evaluated. I guess i have a syntax error.
Second approach:
As i've seen on this other answer I tried setting an env variable
## Grant access to webhook uri
SetEnvIf Request_URI ^/specialUri noauth=1
## Auth config
AuthName "Required login"
AuthType Basic
AuthUserFile C:\path\to\apache\.htpasswd
Require valid-user
## Allow Deny
Order Deny,Allow
Satisfy any
Deny from all
Allow from env=noauth
This resulted on a 401 error Authentication Required when I POST from a http client.
Authentication required!
This server could not verify that you are authorized to access
the URL
"/specialUri".
You either supplied the wrong credentials (e.g., bad password), or your
browser doesn't understand how to supply the credentials required.
In case you are allowed to request the document, please
check your user-id and password and try again.
.htaccess file:
## Grant access to webhook uri
SetEnvIf Request_URI "\specialUri" noauth
## Auth config
AuthName "Required login"
AuthType Basic
AuthUserFile C:\path\to\.htpasswd
## Allow Deny
Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=noauth
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
</IfModule>
I don't really understand why but it seemed that there was a redirection on my site. This was fixed adding another allow directive:
AuthType Basic
AuthName "Required login"
AuthUserFile C:\path\to\.htpasswd
Require valid-user
SetEnvIf Request_URI "mySpecialUri$" allow
Order deny,allow
Deny from all
Allow from env=webhook
Allow from env=REDIRECT_noauth
Allow from 127.0.0.1
Satisfy any
Note that SetEnvIf Request_URI "mySpecialUri$" is using the latest part of the uri. This is because the redirection I mentioned was generating a longer uri.
The Allow from env=REDIRECT_noauth fixed the problem

Getting .htaccess to allow access for specified IP, but request .htpasswd user + password if from any other IP

Ive got a site that im trying to set an .htaccess / .htpasswd password restriction on, but at the same time allow any users with a specific IP address access.
So far ive implemented this as below in my .htaccess file, but for some reason this dosnt work, if i visit the site, no matter from which IP address it allows access, if i comment out the line order deny,allow above the Allow from 192.87.22.18 line, the password protection works, but will request an IP from everyone, even if visiting from the 192.87.22.18 IP (note - not my real IP)
(I haven't published my .htpasswd file for obvious reasons, but it is 1 line containing 1 hashed password)
Any ideas ?
<Files ~ "^\.(htaccess|.htpasswd)$">
deny from all
</Files>
DirectoryIndex index.php
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.example\.co\.uk)(:80)? [NC]
RewriteRule ^(.*) http://example.example.co.uk/$1 [R=301,L]
order deny,allow
<Files ~ "^\.(htaccess|.htpasswd)$">
deny from all
</Files>
AuthType Basic
AuthName "Please enter your ID and password"
AuthUserFile /var/www/vhosts/example.co.uk/subdomains/example/httpdocs/.htpasswd
AuthGroupFile /dev/null
require valid-user
order deny,allow
Allow from 192.87.22.18
# satisfy any
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(/(.*)|$) %{CONTEXT_PREFIX}/$2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule .? %{ENV:BASE}index.php [L]
Through trial and error i ended up using the below which works on apache 2.0, taken from here : https://perishablepress.com/htaccess-password-protection-tricks/
In the above article they wrapped the code block in <IfModule mod_auth.c>
which was causing the code not to run (as i guess the if block equated to false on this server) so i removed them.
# password protect excluding specific ip
AuthName "Username and password required"
AuthUserFile /home/path/.htpasswd
AuthType Basic
Require valid-user
Order Deny,Allow
Deny from all
Allow from 111.222.333.444
Satisfy Any
4 you should use:
AuthType Basic
AuthUserFile c:/wamp/www/_test/www/.htpasswd
AuthName "Protected Area"
<RequireAny>
Require ip 127.0.0.1
Require valid-user
</RequireAny>
order, deny, allow are now Deprecated.

Apache ACL based on environment variable value

I have a vendor Apache module (PingFederate) that sets environment variables based on a token it receives. I would like to control access to directories based on the value of an environment variable.
For example the module sets variables like this:
[PF_AUTH_SUBJECT] => aaron
[PF_AUTH_GROUPS] => CN=Application.E18.Users,OU=Internal,DC=local,CN=Application.E17.Users,OU=Internal,DC=local
I want to secure a directory so that only users in group CN=Application.E18... can access it. My location direction conf looks like this:
<Location /example_app>
SetEnvIf %{PF_AUTH_GROUPS} ^.*CN=Application.E18.Users.*$ ALLOWED
AuthName "ACL PingFederate restricted"
AuthType PFApacheAgent
Order Deny,Allow
Deny from all
Allow from all
</Location>
This doesn't seem to work. I've tried:
SetEnvIf %{PF_AUTH_GROUPS} ^.*CN=Application.E18.Users.*$ ALLOWED
SetEnvIf %{PF_AUTH_GROUPS} ^.*Application.*$ ALLOWED
SetEnvIf %{PF_AUTH_GROUPS} ^.*A.*$ ALLOWED
The only thing that works is:
SetEnvIf %{PF_AUTH_GROUPS} ^.*$ ALLOWED
That obviously won't work.
https://issues.apache.org/bugzilla/show_bug.cgi?id=25725 somewhat intimates that SetEnvIf won't test environment variables but the docs at http://httpd.apache.org/docs/2.2/mod/mod_setenvif.html mentions "an environment variable in the list of those associated with the request", which this should be.
I've also tried mod_rewrite using this:
RewriteEngine On
<Location /example_app>
RewriteCond %{PF_AUTH_GROUPS} ^.*Application.E18.Users.*$
RewriteRule - [E=ALLOWED:1]
AuthName "ACL PingFederate restricted"
AuthType PFApacheAgent
Order Deny,Allow
Deny from all
Allow from all
</Location>
In all of these instances the ALLOWED environment variable is not set.
You'll need to make mod_rewrite execute 2 times to be able to leverage the headers produced by mod_pf, since the latter executes after the former:
RewriteEngine On
RewriteCond %{ENV:REDIRECT_PASS} !1
RewriteRule .* $1 [L,E=PASS:1]
RewriteCond %{HTTP:PF_AUTH_GROUPS} !^.*ECN.*$
RewriteRule .* $1 [L,R=401]
This is also documented here: https://ping.force.com/Support/PingIdentityArticle?id=kA340000000Gs7bCAC

RewriteRule / HTTP auth for one url

I want to redirect "?p_id=62" to http authentification but it does not work.
my conf:
<LocationMatch ^/>
RewriteCond %{QUERY_STRING} !^\?p_id=62$
RewriteRule ^ - [E=NO_AUTH:1,L]
Order deny,allow
Deny from all
AuthType basic
AuthName "Auth Needed"
AuthUserFile "/var/www/site/.htpasswd"
Require valid-user
Allow from env=NO_AUTH
Satisfy Any
</LocationMatch>
Can anyone help?
You don't need to match the ? part of the query string:
RewriteCond %{QUERY_STRING} !^p_id=62$
RewriteRule ^ - [E=NO_AUTH:1,L]
However, this is not going to work. The mod_auth modules are applied before mod_rewrite gets applied, so by the time the rewrite rule checks the query string to set the environment variable, mod_auth has already flagged the request as a 401 (needs auth). You might have to settle for a scripted solution, like:
RewriteCond %{QUERY_STRING} !^\?p_id=62$
RewriteRule ^ /auth_script.php [L]
<Files "auth_script.php">
Order deny,allow
Deny from all
AuthType basic
AuthName "Auth Needed"
AuthUserFile "/var/www/site/.htpasswd"
Require valid-user
</Files>
and the auth_script.php will simply load the content at the $_SERVER['REQUEST_URI'] URI and return it to the browser (not redirect).

htaccess: Conditional Authentication

How can i configure this in my apache/htaccess configuration:
I want HTTP-Authentication for all files with one exception.
The files click.php and js/clickheat.js may be accessed from 1.2.3.4 without any authentication.
I tried FilesMatch, but i can't invert it. So i can't put require valid-user in there. I thought using SetEnv, but how do i check for it later?
<FilesMatch "(click\.php|clickheat\.js)">
# what here?
</FilesMatch>
My other idea was to use mod_rewrite. Well, i can allow access to the two files from the given host and deny it from anywhere else. But how do i chain it with HTTP-Authentication?
# allows access to two files from the given IP
RewriteCond %{REMOTE_ADDR} 1\.2\.3\.4
RewriteCond %{REQUEST_URI} ^/click.php [OR]
RewriteCond %{REQUEST_URI} ^/js/clickheat\.js
RewriteRule (.*) - [L]
# denies everything else
RewriteRule (.*) - [F,L]
So my favourite solution would be enabling HTTP-Auth via RewriteCond/RewriteRule.
Background (or why i want to do this): I'm trying to secure a clickheat (http://www.labsmedia.com/clickheat/index.html) installation. And 1.2.3.4 is the remote running mod_proxy and redirecting access to these to files to our clickheat host.
Ok, i found a solution:
Order Deny,Allow
Deny from All
Satisfy Any
AuthType Basic
AuthName "clickheat"
AuthUserFile /var/www/clickheat/.htpasswd
Require valid-user
<FilesMatch "(click\.php|clickheat\.js)">
Deny from All
Allow from 1.2.3.4
</FilesMatch>
The key is the Satisfy Any which allows either IP- or Auth-based access.