nginx_phantom_token_module icon indicating copy to clipboard operation
nginx_phantom_token_module copied to clipboard

$request_body overwritten (MINOR)

Open gsahbi opened this issue 3 years ago • 6 comments

Nginx $request_body is being overwritten with “token=…” when I try to inspect it in the logs.

Any workaround?

gsahbi avatar Oct 28 '22 08:10 gsahbi

Could you provide a bit more info please, so that we have the best chance of resolving your issue quickly. It seems you're calling an API and receiving an unexpected response:

  • Does the issue occur on every request or intermittently?
  • Could you give us an idea of NGINX configuration, the request / response details and any relevant log entries?
  • Does it only happen under certain conditions, eg large messages, POST requests, when the token expires?
  • Have you only recently started using this plugin or have you been using it for quite a while?
  • Did your API calls work previously and have they only recently stopped working?
  • If it is new behavior, has anything changed recently, such as an upgrade to NGINX or the plugin?
  • What versions of NGINX and the plugin are you using - and which NGINX docker image?

gary-archer avatar Oct 28 '22 09:10 gary-archer

The issue is not related to the function of the plugin itself. I’m getting the correct request body forwarded by nginx to the API server.

The issue is seen only when I try to access the value $request_body from within location directive for example for logging

So to reproduce :

  1. add req_body="$request_body" to the log_format directive
  2. cat /var/log/nginx/access.log will contain

req_body="token=_0XBPWQQ_642208b4-44f6-4e1a-ae1f-180a80c4d359"

gsahbi avatar Oct 28 '22 17:10 gsahbi

I think somehow nginx is confusing the original request body with the introspection request

ngx_snprintf(introspect_body_data, request->headers_in.authorization->value.len, "token=%s", bearer_token_pos);

gsahbi avatar Oct 30 '22 03:10 gsahbi

Ah - I understand your issue now. The module does write its own request body in order to send the introspection request. So this could be a case of needing to set a variable to capture the original request body, before this happens. I will run it by people internally, then take a closer look a little later, to see if we can find you a workaround.

gary-archer avatar Oct 31 '22 08:10 gary-archer

I reproduced this, with the following Docker based configuration. If the module does not run its introspection subrequest then a POST request body is logged correctly. Yet when the introspection subrequest is run, nginx seems to update the $request_body variable as you say.

worker_processes 1;
error_log /dev/stdout info;

daemon on;
load_module modules/ngx_curity_http_phantom_token_module.so;
events { worker_connections 1024; }

http {
    sendfile on;
    proxy_cache_path cache levels=1:2 keys_zone=api_cache:10m max_size=10g inactive=60m use_temp_path=off;
    log_format postdata $request_body;

    server {
        listen 8080;

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
 
        location /api {
            access_log /dev/stdout postdata;
            resolver 127.0.0.11;
            phantom_token on;
            phantom_token_client_credential test-nginx secret2;
            phantom_token_introspection_endpoint curity;
            proxy_pass "http://mockbin.com/request";
        }

        location curity {
            resolver 127.0.0.11;
            proxy_pass http://identityserver:8443/oauth/v2/oauth-introspect;
            proxy_cache_methods POST;
            proxy_cache api_cache;
            proxy_cache_key $request_body;
            proxy_ignore_headers Set-Cookie;
        }
    }
}

Log entries for successful API calls in the /api block then look like this, whereas error responses that do not undergo introspection show the original request body.

req_body="token=_0XBPWQQ_642208b4-44f6-4e1a-ae1f-180a80c4d359"

The cause is not entirely clear yet, and may just be how nginx works when using subrequests. Perhaps options such as ngx_http_discard_request_body and NGX_HTTP_SUBREQUEST_CLONE are related. Also, the proxy_pass directive can still get the original request body:

We will leave this open and dig around some more. I see you have found a LUA based workaround, so no immediate urgency, though it would be good if we could find a way to do this without requiring extra nginx modules, then to write a test for this use case.

gary-archer avatar Oct 31 '22 16:10 gary-archer

as a workaround I used Lua to save request body

access_by_lua '

    ngx.req.read_body()
    ngx.var.req_body = ngx.req.get_body_data()

'; 

gsahbi avatar Nov 03 '22 02:11 gsahbi

This issue might be related to the following configuration that references the request body. Therefore, investigate alternatives and see if we can resolve the original issue.

proxy_cache_key $request_body;

gary-archer avatar Sep 03 '24 11:09 gary-archer