Nginx – Caching nginx auth_request

nginx

I am trying to configure an nginx 1.12.2 reverse proxy to use auth_request and proxy_cache to authenticate requests to a microservice. End users send a simple Bearer token with their request, and the server tries to fetch a resource with it to determine if they are allowed to proceed. That resource fetch should be cached for a given token to take load off the authentication endpoint. Here's my configuration so far:

ssl_certificate                 /etc/nginx/ssl/certificate;
ssl_certificate_key             /etc/nginx/ssl/key;
proxy_cache_path                /var/cache/nginx/auth_cache levels=1:2 keys_zone=auth_cache:1m max_size=1g inactive=60m;
server {
    listen                      80;
    listen                      443 ssl;
    server_name                 myapi.mydomain.com;
    location / {
        proxy_pass              http://myapi/;
        auth_request            /auth;
    }
    location = /auth {
        internal;
        proxy_pass              https://authendpoint.mydomain.com/api/user/verify;
        proxy_cache             auth_cache;
        proxy_cache_key         "$http_x_auth_token$request_uri";            
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

From a client perspective this is working great, but when I look at the nginx server nothing ever gets written to the cache folder. The folder /var/cache/nginx/auth_cache gets created, but is always empty. What could I be missing?

update

Trying this with newer nginx (1.17.9, currently), we still never see anything written to the cache folder. Elsewhere I saw the suggestion that cookies could block caching – this app doesn't use cookies, but we tried anyway:

location = /auth {
    internal;
    proxy_pass              http://authservice/api/user/verify;
    proxy_cache             auth_cache;
    proxy_cache_key         "$http_x_auth_token$request_uri";   
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
    proxy_set_header        X-Original-URI $request_uri;
    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    Set-Cookie;
    proxy_set_header        Cookie "";
}

Still the same behavoir; the auth_cache folder is created, but nothing is ever written there, and requests to our auth endpoint are not cached.

Just for reference, the results from our auth endpoint are extremely minimal:

< HTTP/1.1 200 OK
< Date: Sun, 12 Apr 2020 18:04:08 GMT
< Server: Kestrel
< Content-Length: 0

We've also simplified the remote auth endpoint since I originally asked this question. Now, it is a plain http resource running inside the same cluster as the nginx process. I've updated the example above to reflect that.

final update

On the off chance somebody else tries to use this as a reference, in addition to the two helpful answers below, we needed to fix the cache key in the example above:

proxy_cache_key         "$http_x_auth_token$request_uri";            

Only makes sense if you're actually using X-Auth-Token as a header and not just Authorization. The key above will work, but it means the first proxied auth response for any uri will be cached, and the actual token will be ignored. Really, we needed:

proxy_cache_key         "$http_authorization$request_uri";            

Best Answer

Try upgrading NGINX.

I had the same problem with 1.14.0, where manual requests to /auth with curl were cached, but auth_request sub-requests were not.

After upgrading to NGINX 1.16.1 it started to work.