[PATCH] Allow http_auth_request_module to forward 302 responses

Maxim Khitrov max at mxcrypt.com
Sun Feb 19 13:40:45 UTC 2012

2012/2/18 Maxim Dounin <mdounin at mdounin.ru>:
> Hello!
> On Sat, Feb 18, 2012 at 06:48:50PM -0500, Maxim Khitrov wrote:
>> On Sat, Feb 18, 2012 at 4:45 PM, Maxim Dounin <mdounin at mdounin.ru> wrote:
>> > Hello!
>> >
>> > On Sat, Feb 18, 2012 at 09:19:18AM -0500, Maxim Khitrov wrote:
>> >
>> >> Hello Maxim,
>> >>
>> >> The attached patch allows your http_auth_request_module to forward a
>> >> 302 response and the associated "Location" header to the client. The
>> >> goal is to allow the authentication back end to redirect the client to
>> >> a login page instead of using WWW-Authenticate header.
>> >
>> > You may get the same result by returning 401/403 and using
>> > appropriate error_page handler.  I don't actually see a reason to
>> > handle 302 specially here.
>> Allow me to clarify. I cannot use 401/403 codes, because I need both
>> of those to perform their original function. 403 has to block access
>> without redirecting anywhere and 401 must be used to pass the
>> WWW-Authenticate header.
> Actually you can.  You just need to use some additional processing
> inside error_page handler (or two different error_page handlers,
> selected based on auth request answer), e.g.
>    location / {
>        auth_request /auth;
>        auth_request_set $auth_redirect $upstream_http_location;
>        error_page 403 = /auth_403;
>        ...
>    }
>    location = /auth {
>        proxy_pass http://auth_backend;
>        ...
>    }
>    location = /auth_403 {
>        if ($auth_redirect) {
>            return 302 $auth_redirect;
>        }
>        return 403;
>    }
> And then either set Location (or some other arbitrary header) in a
> 403 response or not.

Thanks, I'll use this, but I really don't like this method. It makes
testing difficult, because when you call the authentication script
directly, which you have to do during the development, you are no
longer receiving normal responses. You get a 403 status and a Location
header that you must now enter manually. Maybe there is some other way
of getting nginx to act on the location, but it just feels like one
hack on top of another.

> [...]
>> Even without this scheme, I think allowing the use of a 302 response
>> would be a useful feature. Relying on the error_page configuration,
>> which I did consider before making my patch, increases the complexity
>> of nginx.conf and could lead to unintended behavior. This way, a
>> single "auth_request /auth;" line takes care of all possible decisions
>> (authenticate/allow/deny/redirect).
> I believe the problem here is how one define "all possible
> decisions".  And I'm really sure that if 302 will be allowed - 303
> and 307 will appear next to it, and then we'll start discussing
> which headers should be passed - e.g. Set-Cookie looks like
> something required in addition to Location.  That's why I
> (intentionally) limited it to only handle 401/403, much like
> normal auth_basic.

Add two extra checks to the outer 'if' statement and 303/307 codes are
handled :)

In practice, most people will not use these due to the uncertainty in
client support and the fact that languages like PHP default to sending
a 302 response when the Location header is set.

As for auth_basic, I don't think this is a fair comparison. What other
things could auth_basic do? It only deals with a single header, which
can easily be handled in the context of the current request. Your
auth_request module could allow for much more flexibility.

> I think correct aproach for the future would be to implement some
> "transparent" mode, much like fastcgi authorizers, where one may
> return arbitrary answer with any headers and body while rejecting
> request.  This is not something trivial to implement as of now
> though, mostly because of body.

Wouldn't redirects take care of this already? You don't need the
authentication script to be the source of extra headers or some html
content. You just need to give it a way of rejecting the request and
pointing the client to a dedicated login page that takes care of
everything else. Your solution with error pages works, but I still
think that allowing redirects would be cleaner.

All you are really gaining with the transparent mode is the ability to
keep the same URL and avoid a redirect for the client. Is the increase
in complexity really worth it?

In any case, thanks for sharing your thoughts on the topic. I'll play
with error_page configuration and see how well I can make it work for
my needs.

- Max

More information about the nginx-devel mailing list