1

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.

Jason
  • 121
  • 5
  • Nginx chooses a location to process a request. It seems that the images are processed by a `location \.php$` block. If you want to authenticate part of the website, you will need to include all of the functionality within the protected `location` block. For example, see [this answer](https://serverfault.com/questions/851282/nginx-location-blocks-dont-apply-to-php-files-inside-them/851285#851285). – Richard Smith Jan 25 '19 at 10:58
  • Thanks for your comment! I forgot to add that there are other users, let's say "open-user-xxx" (as well as "my-user-xxx") that DO NOT need to Basic Auth BUT need to access to the same Rewrite rule directly. Hope you can appreciate I simplified my setup and there are actually quite a few more similar rewrite rules that would be duplicated between Basic Auth and Open users. – Jason Jan 25 '19 at 11:10
  • The rewrite rule does not necessarily need to be protected. Unless `/$1/image_handler.php` is the same for all users. In which case, you may need to use two rewrite rules and make the `.php` block `internal`. – Richard Smith Jan 25 '19 at 11:14

1 Answers1

0

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.
  }
}
Jason
  • 121
  • 5