15

I'm using Nginx (version 1.9.9) as a reverse proxy to my backend server. It needs to perform authentication/authorization based on the contents of the POST requests. And I'm having trouble reading the POST request body in my auth_request handler. Here's what I got.

Nginx configuration (relevant part):

server {
    location / {
        auth_request /auth-proxy;
        proxy_pass http://backend/;
    }

    location = /auth-proxy {
        internal;
        proxy_pass http://auth-server/;
        proxy_pass_request_body on;
        proxy_no_cache "1";
    }
}

And in my auth-server code (Python 2.7), I try to read the request body like this:

class AuthHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def get_request_body(self):
        content_len = int(self.headers.getheader('content-length', 0))
        content = self.rfile.read(content_len)
        return content

I printed out the content_len and it had the correct value. However, the self.rfile.read() will simply hang. And eventually it will time out and returns "[Errno 32] Broken pipe".

This is how I posted test data to the server:

$ curl --data '12345678' localhost:1234

The above command hangs as well and eventually times out and prints "Closing connection 0".

Any obvious mistakes in what I'm doing?

Thanks much!

yty
  • 515
  • 3
  • 11
  • Interestingly, if I use `curl` to post directly to my auth-server, it can read the request body just fine. – yty Nov 17 '16 at 05:34

1 Answers1

14

The code of the nginx-auth-request-module is annotated at nginx.com. The module always replaces the POST body with an empty buffer.

In one of the tutorials, they explain the reason, stating:

As the request body is discarded for authentication subrequests, you will need to set the proxy_pass_request_body directive to off and also set the Content-Length header to a null string

The reason for this is that auth subrequests are sent at HTTP GET methods, not POST. Since GET has no body, the body is discarded. The only workaround with the existing module would be to pull the needed information from the request body and put it into an HTTP header that is passed to the auth service.

JoshRivers
  • 9,920
  • 8
  • 39
  • 39
  • How do you mean "to pull the needed information from the request body". I am stuck on this. – Angshuman Nov 26 '20 at 12:01
  • @Angshuman you could perhaps use the lua module to pre-process the request and read out part of the body, and add it as a header. Thee are probably other solutions as well, but authorization based on POST content with nginx-auth-request-module is probably more trouble than it's worth. – JoshRivers Nov 27 '20 at 19:41
  • Thanks for getting back. Unfortunately I will have to live with the existing modules. Let me know if you can think of other solutions. – Angshuman Nov 28 '20 at 00:37
  • The answer suggests a workaround, but I noticed that variables like `$request_body` and `$query_string` are not forwarded as headers (`proxy_set_header`) to the auth provider when the request to the auth provider is performed. Did no extensive testing, though. – Rainer Rillke May 05 '22 at 15:36