[Twisted-web] Sessions and Authentication for Web2

Phil Mayers p.mayers at imperial.ac.uk
Tue Nov 29 10:26:32 MST 2005


glyph at divmod.com wrote:
> 
> 
> On Mon, 28 Nov 2005 18:18:28 -0800, Kevin Turner <kevin at janrain.com> wrote:
>> On Sun, 2005-11-27 at 21:31 +0000, Phil Mayers wrote:
>>> it seems the "credentials" *are* the HTTP
>>> request object (which in fact is true, given how the HTTP spec is worded
>>> I think?).
>>
>> This is what I tried up doing; including the request in the Credentials.
>> This works a bit, but it really isn't compatible with t.web.guard.
>> Mostly because my Checker ends up doing things to the request, but Guard
>> really had plans to do *other* things with that request once
>> Portal.login returned, so it ends up in a bit of a wreck.  Maybe it
>> would work better if I used a livepage channel instead of a dumb
>> request.
> 
> It would be better if some specific interface were published via 
> wrapping the request, so that the authentication code could be clearly 
> recognizable.  I don't think it makes sense to think of the request 

But the data you need to wrap is different for each mechanism, so all 
that does is move the knowledge of 1 protocol (HTTP) out of the checker 
(which I agree is hacky), and put the knowledge of N mechanisms into the 
protocol.

It's possible this is unavoidable with HTTP :o(

> itself as the authentication interface or the credentials, especially as 
> any interesting HTTP-based authentication scheme (even simple 
> challenge/response digest auth) spans multiple requests.

You're probably right. But there are non-obvious (to me at least) 
difficulties, in particular with keeping the HTTP protocol clear of 
knowledge about the specifics of the auth mechanisms, permitting >1 
WWW-Authenticate challenge header, and keeping the HTTP server free of 
state to route challenge responses back to the appropriate deferreds 
(memory exhaustion attack waiting to happen). And also permitting the 
obligatory HTML-form-based fallback.

I'm having difficulty seeing what it would look like, especially the bit 
of allowing a single portal and list of checkers to support the 
multi-mechanism bit.

You need something pam-like or similar to traverse the checker list with 
"empty" creds, allow all checkers to challenge for their mechanism, then 
pass the challenge-response back to just the single mechanism that's chosen.

At the moment, the best I can come up with is:

class Request(http.Request):
   def process(self):
     variousCreds = []

     if self.isSecure():
       # Can't "challenge" at this stage, he doesn't need to know
       # about us
       variousCreds.append(SSLClientCert(self.sslFoo))

     authz = self.getHeader('Authorization')
     if authz:
       mech, rest = authz.split(' ', 1)
       mech = mech.lower()
       mechCreds = httpMechWrapperFactory(mech, rest, self)
       variousCreds.append(mechCreds)

     # other stuff goes here e.g. URL arguments, pubcookie cookies, etc.

     self.portal.login(variousCreds)

class MultiPortal(Portal):
   def login(self, credlist):
     for c in self.checkers:
       # All or a subset...
       if c.canHandle(credlist):
         return c.login(credlist)
     for c in self.checkers:
       c.maybeChallenge(credlist)

...which starts to look very different from cred as-is

Perhaps this comes from a misunderstanding in the goals? Am I right to 
assume we want to support both the HTTP-standard mechs and also 
HTML-form-based ones? Am I right in assuming >1 mechanism challenge is a 
wanted?

The counter question is, if not, can I assume whatever replaces guard 
will be swappable-out without breaking sessions and/or livepage?



More information about the Twisted-web mailing list