Warm tip: This article is reproduced from serverfault.com, please click

Adding Basic Authentication to Nginx that contains existing Rewrite rules

发布于 2021-01-13 23:30:39

I have images successfully served through a Nginx rewrite rule:

# Rewrite part ==============
location ~* "^/([a-z]{5})/([0-9]{5}).png$" {
  rewrite .* "/$1/image_handler.php?x=$2" last;
}

Now I need to add Basic Authentication to this service. I started with the Basic Auth block below and now my config looks as follows:

# Basic Auth part ===========
location ~ ^/my-user-(?<user_id>[^/]+) {
  try_files $uri $uri/ =404;
  auth_basic "Restricted Content";
  auth_basic_user_file /path/to/passwords/my-user-$user_id;
}

# Rewrite part ==============
location ~* "^/([a-z]{5})/([0-9]{5}).png$" {
  rewrite .* "/$1/image_handler.php?x=$2" last;
}

This works in prompting for login details until the correct password is submitted but afterwards, this time, I get an error (404/500) instead of the image.

I thought that by putting the Basic Auth block above the Rewrite block the flow would be from one block to the other. I now realise that it is because of the "try_files" line in the Basic Auth block.

I tried quite a few variations of Nginx directives including a 404/named location trick inside the Basic Auth block but I got stuck with rules such as "location not allowed inside a named location block", "if is evil"(!), and "rewrite always actions before auth_basic".

Ultimately I cannot find a way a achieve the simple task of adding Basic Authentication to my initial rewrite rule above.

=== UPDATE ===

I forgot to add that there are other users, let's say "open-user-xxx" (as well as "my-user-xxx") that don't need to Basic Auth BUT need to access to the same Rewrite rule directly.

Hope you can appreciate I simplified my setup above and there are actually quite a few more rewrite rules that would be duplicated between Basic Auth and Open users if I had separate blocks for both user types. Thanks.

Questioner
Jason
Viewed
0
Jason 2019-01-25 22:25:08

I am resorted to using the 404/named_location trick I mentioned earlier and overcame the nginx rule restrictions I came across earlier.

Here is what works for me:

# Basic Auth part ===========
location ~ ^/my-user-(?<user_id>[^/]+) {
  auth_basic "Restricted Content";
  auth_basic_user_file /path/to/passwords/my-user-$user_id;

  # Go to Rewrite part
  error_page 404 = @imageHandlers;
}

# Go to Rewrite part anyway (without auth)
error_page 404 = @imageHandlers;

# Rewrite part ==============
location @imageHandlers {
  # Handle image1 ==============
  if ($uri ~* "^/([a-z]{5})/([0-9]{5}).png$") {
    rewrite .* "/$1/image_handler.php?x=$2" last;
  }

  # Handle image2 ==============
  if ($uri ... {
    etc.
  }
}