Perhaps nginx might instead check all requests for a particular signed cookie, verify the signature, if the signature matches, verify that the cookie isn't too old, and then unpack variables from the cookie that the application server might want, such as REMOTE_USER. It seems nginx would then want to freshen-up the cookie.
If the cookie doesn't exist, signature doesn't match, or the cookie has expired, then, nginx should proxy the request to a delegate... but, it should return the results of that delegation directly to the user agent. It'd be the job of the delegate to set/sign the cookie with the information needed when authentication succeeds.
In this way, the authentication agent has full control over the process (so it doesn't have to be in nginx), and, heavyweight authentication is cached.
EDIT: Thanks mixedbit -- you're correct that nginx will forward 3xx onto the client. However, I recall patches are needed to support headers; and, without 200 going to the client, how do you support LDAP form authentication? Even so, an extra sub-request to authenticate each request is still heavyweight.
That's called session handling, which is something you want to implement in your web application, not your web server.
That said, even before this, Apache supported a million different mod_auth_* at http://httpd.apache.org/docs/2.4/mod/ including authentication caching http://httpd.apache.org/docs/2.4/mod/mod_authn_socache.html for modules that don't supply their own cache.
But yeah, there are options in Apache-land, my post was more that nginx could eventually gain those options too :)
tl;dr build your authentication into your app, not the web server layer.
However, the module hasn't been updated in forever, and to build it in recent versions of nginx, I have to turn certain CFLAGS off (i.e. Werror).
Does ngx_http_auth_request_module seem like it could do pubcookie's job? Or perhaps, can I approach this problem using ngx_lua?
For some reason, I thought this behaviour made it to the upstream, till I re-read the official ngx_http_auth_request documentation and realized it doesn't pass through 3xx or headers other than WWW-Authenticate:
The ngx_http_auth_request_module module (1.5.4+) implements
client authorization based on the result of a subrequest.
If the subrequest returns a 2xx response code, the access
is allowed. If it returns 401 or 403, the access is
denied with the corresponding error code. Any other
response code returned by the subrequest is considered
an error. For the 401 error, the client also receives
the “WWW-Authenticate” header from the subrequest response.
Here is a config that does something like this: https://github.com/wrr/wwwhisper/blob/master/nginx/wwwhisper... (deployed here: https://io-mixedbit.rhcloud.com)
(Sorry for the late reply)