How to apply an htaccess rule only on https - apache

So I have a protected folder on a site with an htaccess that forces https and uses basic authentication. The problem is that if I go there using http, it asks for authentication before transferring to https, and then asks for authentication again. Is there a way to make it transfer to https before it prompts me?
Here is the htaccess:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} folder
RewriteRule ^(.*)$ https://site.net/folder/$1 [R,L]
AuthName "Dialog prompt"
AuthType Basic
AuthUserFile /home/user/site.net/folder/.htpasswd
Require valid-user
Update: I've decided to implement my own auth system to bypass this issue.

This is what you can do to show authentication only once:
Set a cookie while redirecting from http to https
Using SetEnvIfNoCase disable authentication when cookie is set
Code you can use:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^filder https://%{HTTP_HOST}/folder%{REQUEST_URI} [R,L,NC,CO=NO_AUTH:1:%{HTTP_HOST}]
SetEnvIfNoCase COOKIE NO_AUTH=1 OKAY
AuthType Basic
AuthName "Dialog prompt"
AuthUserFile /home/user/site.net/folder/.htpasswd
Require valid-user
Order allow,deny
allow from all
deny from env=OKAY
Satisfy any

If you are on Apache 2.4, you can apparently use the conditional structure within your htaccess:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
<If "%{HTTPS} == 'on'">
AuthType basic
AuthName "Private"
AuthUserFile /path/to/passwordfile
Require valid-user
</If>

Related

using rewrite condition with allow and Satisfy directive

I want to create a rule that allows only the https request to be prompted for user credentials and the http request to be redirected .
SetEnvIfNoCase IS_SSL .*yes.* HTTPS_REQUEST
<Files *>
AuthType Basic
AuthName "MyFirstPage"
AuthBasicProvider file
AuthUserFile /indexing/.pwd
Require valid-user
Order Deny,Allow
Allow from env!=HTTPS_REQUEST
Satisfy All
</Files>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{ENV:IS_HTTPS_REQUEST} off [NC]
RewriteCond %{THE_REQUEST} ^GET [NC]
RewriteRule ^(.*)/Mydata.php https://%{HTTP_HOST}/x1/Mydata.php [R=301,L]
</IfModule>
The above code is prompting for the password for both http and https request . Can you please suggest
Regards
You need to change "All" to "Any"
Satisfy Any
That way if the env!=HTTPS_REQUEST is true, the Require valid-user doesn't need to be satisfied.

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).

Apache: Redirect a folder with basic auth to secure server

In the past, users have logged onto a private folder using Basic HTTP authentication. We have upgraded the site by adding a SSL certificate, so that these users are now encouraged to use SSL in order to secure their passwords.
In an attempt to redirect from http://example.com/private/ to https://example.com/private/, I have tried this .htaccess file:
RewriteCond %{HTTPS} =off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
AuthUserFile /usr/home/example/passwd
AuthName "Private Page"
AuthType Basic
The trouble is that when the users navigate to the non-SSL page, it asks them for their authentication first, before the redirect. This defeats the whole purpose.
You can try splitting your rewrite rules and mod_auth instructions:
In vhosts you put, this will be done before perdir .htaccess:
RewriteCond %{HTTPS} =off
RewriteRule ^/?private https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
In /private/.htaccess, you have only mod-auth instructions:
AuthUserFile /usr/home/example/passwd
AuthName "Private Page"
AuthType Basic
If you're using Apache 2.4 you can avoiding the double authentication using configuration sections.
# Redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# Authenticate users only when using HTTPS
<If "%{HTTPS} == 'on'">
AuthType Basic
AuthName "Special things"
AuthUserFile /etc/blah.htpasswd
Require valid-user
</If>

Apache .htaccess redirect to HTTPS before asking for user authentication

This is my .htaccess:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
AuthUserFile /etc/hi
AuthName "hi"
AuthType Basic
require valid-user
It asks for user authentication using http, meaning that password will be sent in plain text. It will than redirect to the https version and ask the password again.
How can i fix it?
If you're running Apache 2.4 you can use configuration sections to solve this quite easily.
Eg...
# Redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# Authenticate users only when using HTTPS
# Enable for <v2.4
# SSLRequireSSL
# ErrorDocument 403 /secure-folder/
# Enable for >v2.4
<If "%{HTTPS} == 'on'">
AuthType Basic
AuthName "Special things"
AuthUserFile /etc/blah.htpasswd
# Prevent this 'Require' directive from overriding any merged previously
<IfVersion >= 2.4>
AuthMerging And
</IfVersion>
Require valid-user
# Enable for >v2.4
</If>
I get around it this way. Just allow Non-SSL since it will be redirected then require auth once on SSL...
SetEnvIf %{SERVER_PORT} ^80$ IS_NON_SSL
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
AuthUserFile /etc/hi
AuthName "hi"
AuthType Basic
require valid-user
Allow from env=IS_NON_SSL
Thank you very much, Istador!
My Apache is of version 2.2 (Synology NAS DSM 5.1) so these two do not work on it:
RewriteOptions Inherit
IfVersion
After taking them (and the section of version >= 2.4) out. The whole thing began to work for me.
There are a lot suggestions out there for this topic, I spent two days to try them out.
But only this one works for me.
Here's what I did:
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
AuthType Basic
AuthName "private area"
AuthUserFile /path/to/file/.htdigest
Order Deny,Allow
Deny from all
Satisfy Any
Allow from env=!HTTPS
Require valid-user
So it's verified to work on Apache 2.2, Synology DSM 5.1.
The checked solution https://stackoverflow.com/a/15940387/2311074 does work on Firefox on Ubuntu 16.04, but it does not work on Firefox on Win 7.
If you want to protect your folder https://yourdomain.com/securefolder
then you need to create in that folder a .htaccess with the following content:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
SSLRequireSSL
ErrorDocument 403 https://yourdomain.com/securefolder
AuthType Basic
AuthName "Admin"
AuthUserFile /outside/your/www/folder/.htpasswd
Require user admin Admin
The way it works is that when you are calling the website through http:// instead of https:// it will redirect you to the error page. The trick is to use the correct link with the https:// as your default error page.
I'm running Apache 2.2 and none of the above solutions worked for me. I found a workaround for me here. Basically, you need to set SSLRequireSSL and use some script language in the ErrorDocument to forward users to HTTPS. Unfortunately, in my case this only works when accessing particular files on the server, it does NOT work if just the domain is provided. Here is what I did:
AuthType Basic
AuthName "Password Protected Area"
AuthUserFile /my/path/to/.htpasswd
#Require valid-user
<FilesMatch "(^(?!ssl.php).*)">
SSLRequireSSL
ErrorDocument 403 /ssl.php
Require valid-user
</FilesMatch>
The regex in FileMatch tells apache to SSLRequireSSL for all files except ssl.php - and forward the user to ssl.php if he tries to access without SSL.
My ssl.php looks like this:
if(!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "" || $_SERVER['HTTPS'] == "off")
{
$redirect = "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
header("HTTP/1.1 301 Moved Permanently");
header("Location: $redirect");
exit;
}
What now happens:
Opening http://example.com/some/file.php forwards to
https://example.com/some/file.php and asks for username &
password.
Opening https://example.com/ connects via https and asks for u/p
Opening https://example.com/some/file.php does basically the same.
Opening http://example.com/ forwards to some default apache server page
The last point is what I am not happy with, if someone has a solution for that, I'd be glad to hear about it. Things I tried to solve this issue:
Changed the regular expression to (^$)|(^(?!ssl.php).*) to explicitly also match empty strings. Did not work
Added a rewrite rule to rewrite an empty string to index.php. Does not work either.
Our client's webapp is installed in his webuser directory. Authorisation is handled before mod_rewrite rules (https://serverfault.com/a/443185/253111), and we could not get the accepted answer to work, so mod_rewrite seemed not an option.
Eventually we explicitly required SSL and used the webapp's root over HTTPS as 403 and 404 error documents. So when one visits any page over HTTP (which is unauthorized, hence the 403) or a non existing page (404), he is being redirected to ie. https://DOMAIN.TLD/~WEBUSER/admin.
This is the .htaccess file with some extra info in the comments.
### INFO: Rewrites and redirects are handled after authorisation
### #link https://serverfault.com/a/443185/253111
### INFO: Log out of a HTPASSWD session
### This was not always possible, but Firefox and Chrome seem to end sessions
### when a new one is trying to be using ie.:
### https://logout:logout#DOMAIN.TLD/~WEBUSER/
### #link http://stackoverflow.com/a/1163884/328272
### FORCE SSL: Explicitly require the SSL certificate of a certain domain to
### disallow unsigned certificates, etc. ErrorDocument commands are used to
### redirect the user to an HTTPS URL.
### #link http://forum.powweb.com/showthread.php?t=61566
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "DOMAIN.TLD"
### HTPASSWD AUTHENTICATION
AuthUserFile /var/www/vhosts/DOMAIN.TLD/web_users/WEBUSER/.htpasswd
AuthType Basic
AuthName "Hello"
Require valid-user
### ERROR DOCUMENTS: Redirect user in case of a 403 / 404.
ErrorDocument 403 https://DOMAIN.TLD/~WEBUSER/admin
ErrorDocument 404 https://DOMAIN.TLD/~WEBUSER/admin
Here is the only solution that worked in one of my configurations:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
<If "%{SERVER_PORT} != '80'">
AuthUserFile /etc/hi
AuthName "hi"
AuthType Basic
require valid-user
</If>
Notably, this is for an Apache 2.4 over which I have no control (shared hosting). It seems that the %{HTTPS} variable is not defined on this config, and any solution based on SSLRequireSSL generated a 500 Internal Server Error.
(Side note: In case you prefer a 403 Forbidden instead of a 301 Permanent Redirect when serving HTTP requests, use RewriteRule ^(.*)$ - [F,L] instead)
Molomby's solution works in 2.4 and higher, but doesn't work with the current Debian version 2.2.22.
Ben's / Chris Heald's solutions also didn't work for me in 2.2.22, but that was due to a different order/satisfy configuration. These settings have changed with 2.4 and the solution seems to be incompatible with 2.4 and above (the redirect works, but the browser is just displaying an unauthorized error without asking for credentials).
Here is a combination of both solutions that should work for versions below and above 2.4:
RewriteEngine on
RewriteOptions Inherit # rewrite rules from parent directories
RewriteCond %{HTTPS} off
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
AuthType Digest
AuthName "private area"
AuthDigestProvider file
AuthUserFile /path/to/file/.htdigest
<IfVersion < 2.4>
Order Deny,Allow
Deny from all
Satisfy Any # reset this to 'All' in custom <Files> and <Directory> directives that block access
Allow from env=!HTTPS
Require valid-user
</IfVersion>
<IfVersion >= 2.4>
<If "%{HTTPS} == 'on'">
AuthMerging And
Require valid-user
</If>
</IfVersion>
Requirements: mod_rewrite, mod_auth, mod_digest, mod_version
None of the above worked for me, but this did. My only concern is if there are certain conditions whereby the auth is not triggered allowing someone access without the credentials. I'm not sure there are, but maybe you bright people may say otherwise.
This code redirects non-www to www and http to https, with .htaccess folder auth.
This is the contents of the htaccess file in the directory you want to protect:
RewriteEngine on
# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/foldername/$1 [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/foldername/$1 [L,R=301]
# Apache 2.4 If
<If "%{HTTPS} == 'on' && %{HTTP_HOST} =~ /www/">
AuthType Basic
AuthName "Protected folder"
AuthUserFile "/home/etc/.htpasswds/public_html/foldername/passwd"
require valid-user
</If>

Force SSL on Apache, with Auth and Canonical redirect

I've read some posts on how to redirect to SSL, also some on how to make sure a site is using the www subdomain / canonical name, and some on how to set up Basic Auth. Here is what I have in my .htaccess file right now:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteEngine on
RewriteCond %{HTTP_HOST} !(^www\.site\.com*)$
RewriteRule (.*) https://www.site.com$1 [R=301,L]
AuthName "Locked"
AuthUserFile "/home/.htpasswd"
AuthType Basic
require valid-user
It works fairly well, but I'd like to optimize it. My questions include:
How do I avoid double authentication? When I access the site w.o. SSL I have to authenticate, and then I am redirected to SSL and have to authenticate again. Can I just be redirected and then authenticated?
It looks like the first rule is pretty awesome because I could use it on any site without modifying it. Can rule #2 be rewritten to be site-independent? ie: it will force www to be used on any site no matter what the domain name is (with a better written rule)? answered here
How would I do the reverse of number 3 with a rule that would work on any site to force the site not to use www, ie redirect to site.com from www.site.com? answered here
For #1
How to avoid double authentication? Can I just be redirected and then authenticated?
Boom! This works.
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "www.askapache.com"
ErrorDocument 403 https://www.askapache.com/admin/
See:
http://www.askapache.com/htaccess/apache-ssl-in-htaccess-examples.html
http://www.askapache.com/htaccess/ssl-example-usage-in-htaccess.html
http://www.askapache.com/htaccess/htaccess.html
Just put that above block at the top of your .htaccess, here is mine:
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "www.askapache.com"
ErrorDocument 403 https://www.askapache.com/admin/
AuthType Digest
AuthName "Protected By AskApache"
AuthDigestDomain / https://www.askapache.com/admin/
AuthUserFile /home/askapache/.htpasswd-digest
Require valid-user
Satisfy All
If you're using Apache 2.4 you can also avoiding the double authentication using configuration sections.
# Redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# Authenticate users only when using HTTPS
<If "%{HTTPS} == 'on'">
AuthType Basic
AuthName "Special things"
AuthUserFile /etc/blah.htpasswd
Require valid-user
</If>
I've given a more refined version of this in my answer here.
For #1:
Set the Auth instructions only on the VirtualHost which is listening on *:443. You should have 2 VirtualHosts, one listening on port 80 and one on port 443. Using AuthType Basic on non-SSL communication is a big issue, username and password are just base64 encoded, so it's in clear on every requests (even images or css) that are used on your http server!
This is my solution in order to prevent double authentications of previous re-writes like:
RewriteCond %{HTTPS} ^off$ [NC]
RewriteCond %{REQUEST_URI} /administrator/*
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R,L]
<If "%{HTTPS} == 'on'">
AuthType Basic
AuthName "Authorization Required"
AuthUserFile /var/www/vHost/etc/HTTP-Basic-Auth/htaccess-Users
AuthGroupFile /var/www/vHost/etc/HTTP-Basic-Auth/htaccess-Groups
#require valid-user
require group Webmins
</If>
<Else>
ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
</Else>
Even though I don't the condition is really required - its more there as an additional security fallback if the Rewrite won't work for some reason.
Thanks for the replied above, it help to create the combined https and www solution. My only concern is if there are certain conditions whereby the auth is not triggered allowing someone access without the credentials. I'm not sure there are, but maybe you bright people may say otherwise.
This code redirects non-www to www and http to https, with .htaccess folder auth.
This is the contents of the htaccess file in the directory you want to protect:
RewriteEngine on
# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/foldername/$1 [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/foldername/$1 [L,R=301]
# Apache 2.4 If
<If "%{HTTPS} == 'on' && %{HTTP_HOST} =~ /www/">
AuthType Basic
AuthName "Protected folder"
AuthUserFile "/home/etc/.htpasswds/public_html/foldername/passwd"
require valid-user
</If>