
David Reid wrote:
c) Exarkun expressed a strong (ok, mandatory) preference for the use of tw.cred in any Authentication solution. However, it was noted that tw.cred does not allow for challenge-response authentication mechanisms (which all of mine are). Specific examples were noted: twisted.protocols.sip, SASL, OTP
Hmm. How did you get this idea? Cred's design was specifically to facilitate challenge-response authentication. That's why login() takes credentials and returns a Deferred. The assumption is that the credentials object will encapsulate whatever facets of the user's connection are required to do the negotiation process.
While it might be a valid assumption, there is no common public interface provided to facilitate it. Perhaps because no one knows what that should look like, perhaps because no one felt it was necessary. But I do believe that something like twisted.protocols.sip.IAuthorizer, that allows for an arbitrary number of round trips should be in cred, either the ICredentials interface should be extended (probably through a subclass) or a new interface should be created. I'm toying with some ideas of how to best do this, but I don't really "get" cred so if you have any requirements other than arbitrary number of round trips, let me know so i can take those into account now rather than later.
I've been thinking more about this and I can indeed now see a slight impedance mismatch that I haven't yet thought my way around. I got here from thinking about implementing Negotiate support using PyGSS. Exarkun and I posted examples of how one might do arbitrary challenge-response by making the creds a proxy object to the protocol instance, and I waved my hands saying "HTTP is a bit more hard because of the statelessness / request-based nature of the protocol". The best I've come up with that in theory supports >1 auth mechanism[1] is here: http://deadbeefbabe.org/paste/2249 To "match" HTTP to t.cred, it seems the "credentials" *are* the HTTP request object (which in fact is true, given how the HTTP spec is worded I think?). There's then a checker that can "check" HTTP requests against sub-mechanisms, and if none work then one or all of them can challenge the request. This seems somewhat hackish as the "checker" then has to know about "name: value" rfc2822-style protocol PDUs, as opposed to just the elements of the auth algorithm. It might be more palatable if you could somehow "chain" checkers - e.g. return an IDigestCreds from requestAvatarId, or maybe have some kind of 2-pass thing? [FreeRadius has an interesting thing in it's "authorize" config section where you first pass the request through the "authorize" section to determine how to authenticate it (and optionally return there and then with challenges etc.) then pass it through just one module as defined by the auth-type. This will mean nothing to you unless you've seen it, but that's what I mean by 2-pass] On the other hand, this is a very flexible system as it permits you to allow based on other portions of the request such as arbitrary headers, SSL cert for the TCP connection, and so on. (Note to all: a load of the code is ripped from the t.p.sip code, so appropriate credit where it's due. The stateless nonce thing might be worth ripping though) Comments welcome. [1] t.w.http does not appear to allow you to set headers >1 time e.g. WWW-Authenticate: basic realm="server.domain.com" WWW-Authenticate: digest realm="...",foo="bar",...