X__
X__

Reputation: 2141

nginx: auth_basic for everything except a specific location

How can I enable HTTP Basic Auth for everything except for a certain file?

Here is my current server block configuration for the location:

location / {
       auth_basic "The password, you must enter.";
       auth_basic_user_file /etc/nginx/htpasswd;
}

location /README {
       auth_basic off;
}

However, on /README, it is still prompting for a password.

How can we fix this?

Thanks! Mark

Upvotes: 30

Views: 42156

Answers (5)

Слава ЗСУ
Слава ЗСУ

Reputation: 485

I think auth_basic off; works for generally simple pages with no reference to any other things that could be linked to the page. So here's the trick:

Actually when you set auth_basic off; for certain uri, you need to be sure there is no reference for any brother-uris!!! But what if it is?

Well, I found no better way then just to track it. By default you need to check /var/log/nginx/access.log for all 401 (unauthorized) statuses once you did a request to the /desired-url which you want to put under location wit auth_basic off; directive.

So what was interesting in access.log? I noticed that once i trigger /desired-url I immediately got reference for /static/ files. What I did?

Simply created new location directive for /static/ path and of course it includes auth_basic off; directive.

Not only one static folder, there was also 401 status for /favicon file and some other files and folders.

So for all of them I simply created new location blocks with auth_basic off; directive. Be aware creating location for new path may not resolve the issue as new path could be following after. So constantly track access.log

I know it looks like a raw/fast solution and definitely can be improved/optimized but so there was nothing on the web that helped me better so here I share my experience.

Upvotes: 0

deathfry
deathfry

Reputation: 744

Only auth_basic off didn't work for me If we have to skip auth for ALL uri's under our url

location ^~ /some/location/to_skip/ {
  auth_basic off;
  try_files $uri $uri/ /index.html;
}      

Upvotes: 0

Kamaradski
Kamaradski

Reputation: 362

I'm doing the following:

location = /hc.php {
  auth_basic "off";
}

location / {
  try_files $uri $uri/ =404;
}
  • The narrow match:location = /somefile.txt {} comes first, so location / {} can capture the remaining requests
  • auth_basic "off" requires the quotes around it as far as I know
  • I also use the exact (full, if you like) match, in order to stop iteration over the other locations defined in the config (read below quote for more info on what it does)

Probably this would work in different orders, and/or without the double quotes also, but why not try to do things as correct and complete as possible, if possible.

The most important modifiers are:

(none) No modifier at all means that the location is interpreted as a prefix. To determine a match, the location will now be matched against the beginning of the URI.

=: The equal sign can be used if the location needs to match the exact request URI. When this modifier is matched, the search stops right here.

~: Tilde means that this location will be interpreted as a case-sensitive RE match.

~*: Tilde followed by an asterisk modifier means that the location will be processed as a case-insensitive RE match.

^~: Assuming this block is the best non-RE match, a carat followed by a tilde modifier means that RE matching will not take place.

quoted from here: https://www.keycdn.com/support/nginx-location-directive

Upvotes: 1

Jason Fisher
Jason Fisher

Reputation: 91

I am doing something similar using "map" instead of "if" to assign the auth_basic realm variable and htpasswd file:

map $http_host $siteenv {
  default       dev;

  ~^(?<subdomain>.+)\.dev dev;
  ~^(?<subdomain>.+)\.devprofile devprofile;
  ~^(?<subdomain>.+)\.devdebug devdebug;
  ~^(?<subdomain>.+)\.test test;
  ~^(?<subdomain>.+)\.demo demo;
  ~^(?<subdomain>.+)\.stage stage;

  # Live
  ~^(?<subdomain>.+)\.live live;
  ~^.*\.(?P<subdomain>.+)\.[a-zA-Z]* live;
}

map $http_host $auth_type {
  default       "Restricted";

  ~^(?<subdomain>.+)\.dev "Development";
  ~^(?<subdomain>.+)\.devprofile "Development";
  ~^(?<subdomain>.+)\.devdebug "Development";
  ~^(?<subdomain>.+)\.test "Testing";
  ~^(?<subdomain>.+)\.stage "Stage";
  ~^(?<subdomain>.+)\.demo "Demo";

  # Live
  ~^(?<subdomain>.+)\.live "off";
  ~^.*\.(?P<subdomain>.+)\.[a-zA-Z]* "off";
}

server {
  .. etc ..

  auth_basic            $auth_type;
  auth_basic_user_file  /etc/nginx/conf.d/htpasswd-$siteenv;
}

Upvotes: 9

Sergei Lomakov
Sergei Lomakov

Reputation: 2061

Try to use sign = , that helps you:

location = /README {
       auth_basic off;
       allow all; # Allow all to see content 
}

Upvotes: 44

Related Questions