[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