[Zope-PAS] Challengers (and Zope 3)

Jim Fulton jim at zope.com
Thu Sep 30 18:19:48 EDT 2004

Mark Hammond wrote:
>>OK, this idea seems to have some potential.  I suggest the following
>>algoritm then:
>>   # PAS challenge algorithm:
>>   protocol = None
>>   for chalenger in challengers:
>>       protocol = challenger.challenge(request, response, protocol)
>>   if protocol is None:
>>       # no challengers fired
>>       ... do fallback thing
>>Challenge methods, then, should be written along the lines of:
>>   def challenge(self, request, response, protocol):
>>       if protocol is None:
>>           ... do stuff (e.g. set response status for http)
>>           return self.protocol
>>       elif protocol == self.protocol
>>            ... do other stuff, often a subset of stuff
>>            ... done when protocol is None (e.g. for http, don't set
>>            ... 401 status)
>>       # we do nothing if protocol doesn't match
>>       return protocol
> The 'protocol is None' and 'protocol==self.protocol' cases are not clear to
> me.  Can you sketch out what HTTP would specifically look like in those 2
> branches?  At the moment, it need only do 2 things - set 401, and set a
> header.

Right. In the protocol is None case, it sets the status and sets the header.

In the protocol == self.protocol case, it leaves the status alone (or
checks that it is 401 if it's paranoid) and *adds* a new header
(for the new challenge).

> Other issues that hang over from the existing implementation:
> * Who sets the response body?  In CVS PAS, that is done by the HTTP
> challenger.  If a site admin disables HTTP auth, then an empty body is
> returned as a response.  I am guessing that is the "is None" part above?

In Zope 3, this is done by the exception view by the Unauthorized Exception.
If challengers need to be able to do this, then we will probably need to
add better apis for response manipulation, which we probably need anyway.

In Zope 2, the challenger might do this in the "is None" case as you suggest.

> * The current implementation still has a problem in that it neglects to
> override response._unauthorized().  This method adds HTTP basic auth
> headers - so even when HTTP auth is disabled, you can end up with a HTTP
> challenge being issued.

Could be. I'm working on the Zope 3 version. ;)

In Zope 3, there is no response._unauthorized.

> * HTTPAuth must do an "addHeader" rather than "setHeader" - the headers
> *must* be gathered in the same order that the challengers fired (so that the
> plugin order directly affects the authenticate header order)


>>I'll be a sprint next week where I think we can try this out for
>>basic, digest, and cookie/redirect challengers, where basic and digest
>>auth would use the http protocol.
> Sounds great!  Hopefully one day my sample with a mock-up of the NTLM
> protocol will come in useful.

This will be a Zope 3 sprint BTW.


Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org

More information about the Zope-PAS mailing list