Django response with two HTTP 'WWW-Authenticate' headers

219 views
Skip to first unread message

Alexey Gusev

unread,
Jan 20, 2014, 7:51:05 AM1/20/14
to django...@googlegroups.com

Im developing small intranet web service. I want authenticate users over kerberos in MS AD or with basic auth. For that reason i need to set two 'WWW-Authenticate' http headers in response 401. How can i do it with Django ?

Should be something like this:

Client: GET www/index.html

Server: HTTP/1.1 401 Unauthorized
        WWW-Authenticate: Negotiate
        WWW-Authenticate: Basic realm="corp site"

This code overwrite header:

def auth(request):
    response = None
    auth = request.META.get('HTTP_AUTHORIZATION')
    if not auth:
        response = HttpResponse(status = 401)
        response['WWW-Authenticate'] = 'Negotiate'
        response['WWW-Authenticate'] = 'Basic realm="  trolls place basic auth"'

    elif auth.startswith('Negotiate YII'):
        ...

    return response

Tom Christie

unread,
Jan 20, 2014, 3:54:32 PM1/20/14
to django...@googlegroups.com
No, I don't believe that Django's response class supports that slightly esoteric usage.

As explained by the stackoverflow answer here, repeated headers should be treated as being the same as a single header containing a comma separated list of values.
That answer appears to indicate that it's valid for the WWW-Authenticate header to be used in this way, so 'Negotiate, Basic relam= ....'.

Also see RFC 2616, Sec 14  "if more than one WWW-Authenticate header field is provided, the contents of a challenge itself can contain a comma-separated list of authentication parameters.", however I wouldn't be at all surprised if some client libraries don't correctly interpret that for you.

Hope that helps...

  Tom

Tom Evans

unread,
Jan 20, 2014, 4:24:34 PM1/20/14
to django...@googlegroups.com
Impossible to do with base classes, but django allows you to customize
your responses however you like:

class MultiAuthResponse(HttpResponse):
www_auth_headers = [ ]
def serialize_headers(self):
base_headers = super(MultiAuthResponse, self).serialize_headers()
extra_headers = '\r\n'.join([ 'WWW-Authenticate: %s' %
hdr.encode('us-ascii') for hdr in self.www_auth_headers ])
return base_headers + extra_headers

response = MultiAuthResponse(status=401)
response.www_auth_headers = [ 'Negotiate', 'Basic realm="trolls place
basic auth"' ]

Cheers

Tom
Reply all
Reply to author
Forward
0 new messages