[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