[nginx] allowing auth_request to proxy TOO_MANY_REQUESTS

Maxim Dounin mdounin at mdounin.ru
Wed Oct 12 13:43:15 UTC 2022


Hello!

On Wed, Oct 12, 2022 at 11:04:50AM +0200, Anders Nicolaisen via nginx-devel wrote:

> Thanks!
> This does make sense, and one might be able to create a somewhat working
> example using this.
> 
> However, this seems to introduce a couple of drawbacks, and kind of
> breaks the semantics of the 'auth_request'.
> 
> Let me illustrate:
> 
> First of all, having auth_request in the server context guards against
> any newly added locations that might yet be missing rules handled
> by the authentication server.
> So, whenever a new location is added, the authentication server needs
> to be updated as well before any requests can be redirected.
> This will most often actually be a good thing in an environment with
> a lot of rules and multiple developers.
> 
> Second, if multiple developers are editing the configurations, they are
> not required to remember the 'internal' in order to bar these from
> outsiders,
> as this would be automatically imposed via auth_request.
> 
> It seems to be more in line with the current semantics of auth_request,
> and also by far cleaner code/configurations, by having auth_request be
> able to relay this one more status code.

Sure, details of the X-Accel-Redirect semantics is different from 
the one provided by auth_request.

If you prefer auth_request semantics, you can do the same with 
auth_request and appropriate handling of the 403 errors, for 
example (assuming the auth backend cannot be modified and returns 
429):

server {
   listen 8080;

   location / {
       auth_request /auth;
       error_page 403 = /error;
       proxy_pass ...
   }

   location = /auth {
       error_page 429 = /limit;
       proxy_intercept_errors on;
       proxy_pass http://127.0.0.1:8081;
   }

   location = /limit {
       set $limit 1;
       return 403;
   }

   location = /error {
       if ($limit) {
           return 429;
       }
       return 403;
   }
}

server {
   listen 8081;

   # an example X-Accel-Redirect server
   # which rejects requests with 'foo' header set to a true
   # value

   if ($http_foo) {
       return 429;
   }

   return 204;
}

The general issue with "having auth_request be able to relay this 
one more status code" as I see it is that it's not just one status 
code.  For example, request limiting in nginx by default uses 503 
status code, and it is not clear why 429 handling should be 
different.  Further, there is the Retry-After header field, which 
is optional, though may appear in both 429 and 503 responses.  
Further, there are other temporary conditions which might be 
considered, such as 413 (with Retry-After) or 502/504 errors.  
Trying to extend auth_reqest to handle unrelated response codes is 
going to result in a lot of additional logic there, which is not 
needed in most configurations and will complicate things.  And 
this is something I would prefer to avoid, especially given that 
the desired handling can be easily implemented simply by writing 
an appropriate configuration.

> P.S.:
> I tried to test your suggestion with this simple conf:
> -----
> server {
> 
>   location / {
>     proxy_pass http://localhost:8888/auth;
>   }
>   location @content {
>     proxy_pass http://localhost:8888/;
>   }
> }
> ----
> 
> And got this error:
> 
> ===
> 2022/10/12 08:51:09 [emerg] 1451#1451: "proxy_pass" cannot have URI part in
> location given by regular expression, or inside named location, or inside
> "if" statement, or inside "limit_except" block
> ===
> 
> I'm guessing I just did something wrong, but the error message seems to
> tell me that it is
> not possible to do it this way.

In named locations there are no location prefix to replace with 
the URI part specified in proxy_pass, so you should use proxy_pass 
without URI part, that is, "proxy_pass http://localhost:8888;", 
note no "/" at the end.

See here for details:

http://nginx.org/r/proxy_pass

Hope this helps.

-- 
Maxim Dounin
http://mdounin.ru/



More information about the nginx-devel mailing list