It's probably easiest to just show by example where I'm hitting issues, so I'll jump right in...
This snippet will work as-is for Nginx with rewrite/auth modules enabled. So hopefully this issue is quick & easy reproduce on pretty much any Nginx install...
server { listen 8081; add_header x-user bar; return 200; } server { listen 8080; location = /auth { internal; proxy_pass http://localhost:8081; } location / { auth_request /auth; auth_request_set $foo $upstream_http_x_user; add_header x-test $foo; add_header success true; proxy_pass http://example.com/; } }
The above example Nginx site config does the following:
- Sends any request to
/auth
via anauth_request
call - The /auth location sends the request to another server which adds a header
x-user bar
auth_request_set
sets a new var$foo
based on the upstream header value ofx-user
set in step 2 above.- A new header is set
x-test
which is set to the value of$foo
- The request proceededs to an external destination.
Response is exactly how I would expect, and confirmed the $foo
var was set correctly:
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test' HTTP/1.1 200 OK x-test: bar
So, here comes the problem...
I need to adjust this config so that it'll return 403 if the value of the upstream header is incorrect.
Seemed like a simple task. So I added an if{}
conditional to check the header:
location / { auth_request /auth; auth_request_set $foo $upstream_http_x_user; # this 'if' is the only part added to the original config if ($foo != bar) { return 403; } add_header x-test $foo; add_header success true; proxy_pass http://example.com/; }
The if
conditional evaluated true so I got a 403, which is not what I was expecting. So, this does not work:
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test' HTTP/1.1 403 Forbidden
I realize that if is evil however I seem to be using it just to return which should be ok. I'm open to using any method to accomplish the same goal - with or without if, so I'm open to ideas!!
I have tried doing things like moving the auth_request
and/or the if
statements into the server{}
block but nothing seems to make this evaluate the way I was expecting.
Further Troubleshooting / Details:
I have verified the problem is that the if
is evaluated BEFORE the auth_request_set
is
location / { auth_request /auth; auth_request_set $foo $upstream_http_x_user; if ($foo != bar) { # x-test never gets set because $foo is null when if evaluates add_header x-test $foo always; add_header success false always; return 403; } add_header x-test $foo; add_header success true; proxy_pass http://example.com/; }
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success' HTTP/1.1 403 Forbidden success: false
I have verified this is not an issue if using set
instead of auth_request_set
. This works (but doesn't accomplish the goal):
# set works, but not auth_request_set location / { set $foo bar; if ($foo != bar) { return 403; } add_header x-test $foo; add_header success true; proxy_pass http://example.com/; }
This config works. set
is evaluated before if
:
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test' HTTP/1.1 200 OK x-test: bar
The behavior persists even if the auth_request
is in the server{}
context:
server { listen 8081; add_header x-user bar; return 200; } server { listen 8080; auth_request /auth; auth_request_set $foo $upstream_http_x_user; location = /auth { internal; proxy_pass http://localhost:8081; } location / { if ($foo != bar) { return 403; } add_header x-test $foo; add_header success true; proxy_pass http://example.com/; } }
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success' HTTP/1.1 403 Forbidden success: false
I've reviewed the following docs and questions:
- Can I compare a variable set by auth_request_set after the auth_request has returned in nginx?
- https://stackoverflow.com/questions/73431103/cant-access-added-headers-using-nginx-auth-request-set
- Nginx $upsteam_cache_status custom header will not appear
- auth_request doesn't block return directive, can't return status?
- https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil
- http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
- http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
- https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
auth_request
in theserver
context?auth_request
andauth_request_set
in server context, and a mix with onlyauth_request
in server andauth_request_set
in location. All return 403 every time.