htaccess exclude one url from Basic Auth
Asked Answered
M

9

86

I need to exclude one Url (or even better one prefix) from normal htaccess Basic Auth protection. Something like /callbacks/myBank or /callbacks/.* Do you have any hints how to do it?

What I'm not looking for is how to exclude a file. This has to be url (as this is solution based on PHP framework, and all urls are redirected with mod_rewrite to index.php). So there is no file under this URL. Nothing.

Some of those urls are just callbacks from other services (No IP is not known so I cannot exclude based on IP) and they cannot prompt for User / Password.

Current definition is as simple as:

AuthName "Please login."
AuthGroupFile /dev/null
AuthType Basic
AuthUserFile /xxx/.htpasswd
require valid-user 
Manysided answered 23/1, 2012 at 20:26 Comment(0)
C
74

If you are using Apache 2.4, SetEnvIf and mod_rewrite workarounds are no longer necessary since the Require directive is able to interpret expressions directly:

AuthType Basic
AuthName "Please login."
AuthUserFile "/xxx/.htpasswd"

Require expr %{REQUEST_URI} =~ m#^/callbacks/.*#
Require valid-user

Apache 2.4 treats Require directives that are not grouped by <RequireAll> as if they were in a <RequireAny>, which behaves as an "or" statement. Here's a more complicated example that demonstrates matching both the request URI and the query string together, and falling back on requiring a valid user:

AuthType Basic
AuthName "Please login."
AuthUserFile "/xxx/.htpasswd"

<RequireAny>
    <RequireAll>
        # I'm using the alternate matching form here so I don't have
        # to escape the /'s in the URL.
        Require expr %{REQUEST_URI} =~ m#^/callbacks/.*#

        # You can also match on the query string, which is more
        # convenient than SetEnvIf.
        #Require expr %{QUERY_STRING} = 'secret_var=42'
    </RequireAll>

    Require valid-user
</RequireAny>

This example would allow access to /callbacks/foo?secret_var=42 but require a username and password for /callbacks/foo.

Remember that unless you use <RequireAll>, Apache will attempt to match each Require in order so think about which conditions you want to allow first.

The reference for the Require directive is here: https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#require

And the expression reference is here: https://httpd.apache.org/docs/2.4/expr.html

Corrinacorrine answered 11/11, 2015 at 16:32 Comment(6)
I had to remove the double-quotes around the Require expr for it to work on apache 2.4.7. Other than that worked perfectly.Labio
I too had to remove the double-quotes but it worked perfectly.Finella
Does not work on my Apache 2.4.10 / cakephp 3 installation. I want to exclude /rest, which is a virtual path (rewrite rule). Can't figure out, why it's not working.Uis
@stephan-richter I suspect because the %{REQUEST_URI} value is the rewritten string. For Cake 3, that ends up pretty much always being /webroot/index.php. You may have to come up with an alternative approach, such as using Cake itself to handle the authentication of routes.Corrinacorrine
You are right. Posted a question on this issue and found the answer myself: #41078395Uis
Can't understand why this overly-simplified syntax Require expr %{REQUEST_URI} =~ m#.*well-known.*# does not exclude from authentication the URL http://<server>/.well-known/acme-challengeRomeyn
L
93

Using SetEnvIf, you can create a variable when the request starts with some path, then use the Satisfy Any directive to avoid having to login.

# set an environtment variable "noauth" if the request starts with "/callbacks/"
SetEnvIf Request_URI ^/callbacks/ noauth=1

# the auth block
AuthName "Please login."
AuthGroupFile /dev/null
AuthType Basic
AuthUserFile /xxx/.htpasswd

# Here is where we allow/deny
Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=noauth

The allow/deny chunk of directives says that deny access for EVERYONE, except when there is a valid-user (successful BASIC auth login) or if the noauth variable is set.

Livi answered 23/1, 2012 at 23:1 Comment(7)
I added this section in <VirtualHost *:80> DocumentRoot /var/www/Symfony/web/ <Directory /var/www//Symfony/web> but its not working.Ufo
Could you please explain, why <Files> does not work here?Dyanne
Thanks! Really helped me out, be careful of case - I had Order deny,allow and it wouldn't work. Needless to say very frustrating!Taurus
may require an Allow from env=REDIRECT_noauth for rewriten urls. Might have been the problem with @vishal. Have a look here: [https://mcmap.net/q/243670/-exclude-specific-cakephp-controller-from-http-basic-auth]Uis
If your public HTML page <link>s to any other file on your server be sure to except it too. Took me way too long to figure out why I was still getting an auth dialog.Potherb
I need both lines Allow from env=noauth and Allow from env=REDIRECT_noauth for it to work.Citrange
This is the Apache 2.2 syntax that is long obsolete. httpd.apache.org/docs/2.4/upgrading.html describes the existence of mod_access_compat, but the initial release of 2.4 was in 2012, so we should probably cease encouraging compatibility with 2.2.Ferdelance
C
74

If you are using Apache 2.4, SetEnvIf and mod_rewrite workarounds are no longer necessary since the Require directive is able to interpret expressions directly:

AuthType Basic
AuthName "Please login."
AuthUserFile "/xxx/.htpasswd"

Require expr %{REQUEST_URI} =~ m#^/callbacks/.*#
Require valid-user

Apache 2.4 treats Require directives that are not grouped by <RequireAll> as if they were in a <RequireAny>, which behaves as an "or" statement. Here's a more complicated example that demonstrates matching both the request URI and the query string together, and falling back on requiring a valid user:

AuthType Basic
AuthName "Please login."
AuthUserFile "/xxx/.htpasswd"

<RequireAny>
    <RequireAll>
        # I'm using the alternate matching form here so I don't have
        # to escape the /'s in the URL.
        Require expr %{REQUEST_URI} =~ m#^/callbacks/.*#

        # You can also match on the query string, which is more
        # convenient than SetEnvIf.
        #Require expr %{QUERY_STRING} = 'secret_var=42'
    </RequireAll>

    Require valid-user
</RequireAny>

This example would allow access to /callbacks/foo?secret_var=42 but require a username and password for /callbacks/foo.

Remember that unless you use <RequireAll>, Apache will attempt to match each Require in order so think about which conditions you want to allow first.

The reference for the Require directive is here: https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#require

And the expression reference is here: https://httpd.apache.org/docs/2.4/expr.html

Corrinacorrine answered 11/11, 2015 at 16:32 Comment(6)
I had to remove the double-quotes around the Require expr for it to work on apache 2.4.7. Other than that worked perfectly.Labio
I too had to remove the double-quotes but it worked perfectly.Finella
Does not work on my Apache 2.4.10 / cakephp 3 installation. I want to exclude /rest, which is a virtual path (rewrite rule). Can't figure out, why it's not working.Uis
@stephan-richter I suspect because the %{REQUEST_URI} value is the rewritten string. For Cake 3, that ends up pretty much always being /webroot/index.php. You may have to come up with an alternative approach, such as using Cake itself to handle the authentication of routes.Corrinacorrine
You are right. Posted a question on this issue and found the answer myself: #41078395Uis
Can't understand why this overly-simplified syntax Require expr %{REQUEST_URI} =~ m#.*well-known.*# does not exclude from authentication the URL http://<server>/.well-known/acme-challengeRomeyn
R
8

This solution works pretty well, you just need to define whitelist you want to pass through.

SetEnvIfNoCase Request_URI "^/status\.php" noauth

AuthType Basic
AuthName "Identify yourself"
AuthUserFile /path/to/.htpasswd
Require valid-user

Order Deny,Allow
Deny from all
Allow from env=noauth

Satisfy any
Raspy answered 14/2, 2013 at 9:17 Comment(0)
Q
6

I tried the other solutions but this is what worked for me. Hopefully it will be of help to others.

# Auth stuff
AuthName "Authorized personnel only."
AuthType Basic
AuthUserFile /path/to/your/htpasswd/file

SetEnvIf Request_URI "^/index.php/api/*" allow
Order allow,deny
Require valid-user
Allow from env=allow
Deny from env=!allow
Satisfy any

This will allow the api url and any url string after /index.php/api/ to open without having to login and anything else will be prompted to login.

Example:

mywebsite.com/index.php/api will open without being prompted to login mywebsite.com/index.php/api/soap/?wsdl=1 will open without being prompted to login mywebsite.com will be prompted to login first

Queeniequeenly answered 22/12, 2016 at 18:4 Comment(1)
BEST of the best solution, all the other ones did not work. Thank you for providing it!!!Enquire
P
2

None of this worked for me with Apache 2.4, because my PHP/Laravel htaccess did a rewrite and changed Request_URI to be always /index.php.

I used Require expr %{THE_REQUEST} to get the first line of the HTTP request (THE_REQUEST) which remains unchanged.

e.g., "GET /callbacks HTTP/1.1"

This worked for me:

    <Location />
        AuthType Basic
        AuthName "Restricted Content"
        AuthUserFile /etc/apache2/.htpasswd
        Require expr %{THE_REQUEST} =~ m#^GET /callbacks#
        Require valid-user
    </Location>

Note you need to change GET to POST if you need to or allow both:

        Require expr %{THE_REQUEST} =~ m#^GET /callbacks#
        Require expr %{THE_REQUEST} =~ m#^POST /callbacks#
        Require valid-user

More about Require expr

Pearman answered 9/12, 2022 at 10:6 Comment(0)
D
1
<location />
        SetEnvIf Request_URI "/callback/.*" REDIRECT_noauth=1

        AuthType Basic
        AuthName "Restricted Files"
        AuthUserFile /etc/httpd/passwords/passwords
        Order Deny,Allow
        Satisfy any
        Deny from all
        Allow from env=REDIRECT_noauth
        Require user yournickname
</location>
Douglasdouglashome answered 21/6, 2013 at 15:11 Comment(0)
N
0

Another approach works like this, if the area you are protecting has a monolithic PHP script controlling everything, like Wordpress. Set up Authentication with in a different directory. Put an index.php there that sets a cookie on path '/'. Then in Wordpress (for example), check the cookie, but bypass the check if $_SERVER['REQUEST_URI'] is the excluded URL.

On my shared hosting platform, RewriteRule could not set an environment variable that worked with "Satisfy any".

With any approach, watch out that the page you are protecting does not include images, stylesheets, etc., that trigger an authentication request when the page itself does not.

Natalya answered 17/2, 2013 at 15:34 Comment(0)
F
0

Add below code to your root htaccess file and don't forget to change your admin url, .htpasswd file page.

<Files "admin.php">
        AuthName "Cron auth"
        AuthUserFile E:\wamp\www\mg\.htpasswd
        AuthType basic
        Require valid-user
    </Files>

Create .htpasswd file in your root folder and add below username and password (set default username:admin and password: admin123)

admin:$apr1$8.nTvE4f$UirPOK.PQqqfghwANLY47.

Please let me know if you still facing any issue.

Foeticide answered 19/4, 2016 at 10:29 Comment(0)
F
0

why don't you just use basic auth the way it was intended?

user:[email protected]/callbacks/etc
Fibrin answered 3/11, 2017 at 2:55 Comment(1)
Well, because a) no one really wants™ auth data in the URI string, and b) because it's likely that OP has not the opportunity to customize the call (since he's talking about callbacks from a bank, I assume he's unable to change the behaviour on the client side)Gravity

© 2022 - 2024 — McMap. All rights reserved.