[Twisted-Python] twisted cred: why does avatarId need to be a str?

Glyph Lefkowitz glyph at twistedmatrix.com
Sun Sep 12 02:04:39 EDT 2010

On Sep 10, 2010, at 1:01 PM, Laurens Van Houtven wrote:

> Okay, to be specific: I believe the appropriate interface is IResource. This is in line with t.web's general way of interacting with cred: you give me credentials, I give you a protected IResource.

This doesn't quite make sense to me.

Mostly, I don't understand what the moving pieces are here.  If this is all to implement a "token endpoint" which doesn't "actually serve protected resources", then what is the IResource being returned by the realm actually *doing*?  If it is not, itself, a "protected resource", then isn't the amount of stuff that its IResource can do severely restricted (i.e. restricted to doing a few OAuth-specific HTTP things) and therefore actually an avatar of a completely different, OAuth-specific interface, which just happens to be wrapped in an IResource by the OAuth implementation for the benefit of formatting those OAuth-specific things over an HTTP channel?

Based on what you've said, I would expect the avatar interface to be 'IToken', since the point of this authentication is to 'generate tokens'.

> It sounds like OAuth is very precisely implementing something that maps almost exactly onto the checker part of cred, but you're doing it by implementing a realm to allow applications to provide their own logic.  This might not be the wrong idea, but it needs to be spelled out very clearly.
> Doing everything in the checker probably might make more sense. The reason I originally thought to do this in the IRealm is that I figured credentials checkers should just check credentials, and creating a new credential (the access token) wasn't part of ICredentialsChecker's job (more like IRealm's job). Apparently I was mistaken.

I'm going to handwave a bit here and pretend we're talking about a thing that actually does serve arbitrary resources, so my answers may be slightly off.  But I think they may be applicable either way.

Speaking the authentication protocol is the authentication implementation's job, not the realm or the checker.  For example: if you need to generate a challenge as part of the authentication process, the checker probably doesn't need to get involved there.  If you need to ask the checker something about the challenge (let's say you have a list of persistent salts), then there needs to be a method on the credential interface to allow the checker to relay that information back.

It strikes me that creating a new access token is also an authentication feature.  If it is, then it goes into the OAuth resource somewhere.  If it needs to be pluggable then it needs to go into the ICredentialsChecker or possibly the realm, but it's possible that this is just an OAuth specific interface that is plugged in to the OAuth-doing IResource separately, as a constructor argument that has nothing to do with cred.

> As you describe it:
>> token endpoints let you trade in some credentials that prove you're supposed to have access for a token that actually *gives* you that access
> In cred-ese, that would be "checkers let you trade in some credentials that prove you're supposed to have access for an <avatar ID, which you give to a Realm> that actually *gives* you that access".  As far as the OAuth response is concerned, it's like a checker.  Looking at the individual parts, assuming that the avatar interface for the purposes of this discussion is IResource, it breaks down like this in my mind:
>>     - the access token (an ascii string, mandatory)
> Avatar ID.  (See, it's a str!)
> Heh, okay; as long as there's a plausible way to get the other important information (see rest of email) into the HTTP response, I'll believe you.

Yes.  The way to get it into the HTTP response is: put it into the HTTP response :).  You don't necessarily need to cram it into the realm.

>>     - the expiration time (optional)
> Implementation detail of the session.  Avatars are actually sessions, which expire: sometimes (as with POP) at the end of a connection, sometimes (as with nevow.guard's HTTP support) with a session timeout.
> Right, but:
> a) The avatar needs to know about this timeout, since the timeout information needs to be able to make it into the HTTP response.

I'll stop you right there: No.  (We can skip the rest of points b, c, and d, since they all apparently follow from this.)

The avatar's job is to give you an IResource, but the OAuth implementation doesn't necessarily need to pass through either the arguments to that resource or that resource's return values (from getChild or render) exactly.  If the timeout needs to be put into the HTTP response as a header, the OAuth resource could wrap the IResource value that it gets from the realm and set the header before calling the ultimate resource's child.

Note that this isn't just the credentials checker: this is the OAuth implementation.  Relaying information there is easy though: depending on how the checker itself gets created and parameterized, either you can have the checker simply have a reference back to the OAuth resource so it can call some methods, or you can expand the OAuth credentials interface to have a method that the checker uses to pass that information back along with the resource.

>>     - the refresh token (another ascii string, similar to the access token, optional)
> Implementation detail of the authentication protocol.  The client library and server library should be transparently refreshing this without telling either the client application code or server application code, right?
> Sure, but we're still writing library code here.

> If the avatar interface isn't actually IResource, but a new interface IAccessToken, getting the refresh token later might be feasible. (It should be a different interface, because in order to create a refresh token outside of this entire cred cycle, I need to know about the thing it's refreshing -- so, the information in the response needs to be easily accessible and not just an opaque IResource).
> I agree entirely that clever client library code would abstract this mess away from application code. However, right now this code still needs to somehow be able to eventually produce HTTP responses that don't abstract anything yet and just contain all the appropriate data, because that's just what the OAuth spec says it needs to be able to do. There isn't any real application code in the token endpoint; they're pretty similar for all OAuth setups, and customization would typically happen through implementing the appropriate ICredentialsChecker.

Again: producing HTTP responses is not the same thing as producing IResource implementations.  You can have an HTTP response produced by an IResource that wraps another IResource and adds some special sauce to the response.  So this information still never needs to make it to the realm.

>>     - scope (an ascii string consisting of a set of space-separated words, optional)
> This part doesn't quite fit, but could be expressed in one of two ways: a modification to the avatar ID, or as some extra structure on the Mind that modifies what functionality the Realm bundles in to your avatar implementation (without changing the interface provided by that object, of course).
> Unfortunately I don't believe this can be done through the mind. Again working under the previous assumption that ICredentialsChecker and not the IRealm is responsible for creating the access token, and scope is known to the thing that makes the access token, the ICredentialsChecker knows about the scope. Unfortunately the only way to pass stuff  between the ICredentialsChecker and the IRealm is the avatar ID, so you don't have a choice.

OK, I admit it, by the time I get here I'm lost.  We should try to meet up and have an interactive conversation about this, because I have a ton of questions about this, and I don't understand who generates the scope ID and why, and why this bit of information would need to be relayed between the checker and the realm in the process of authentication.  Basically this goes back to the first confusion I mentioned at the beginning of this email: I don't understand why the realm is giving back an IResource if the whole purpose is to just generate tokens and return them.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20100912/434b4157/attachment-0001.htm 

More information about the Twisted-Python mailing list