[Twisted-Python] Fitting cred into my application

Matthew Pounsett matt at conundrum.com
Sat Sep 22 23:41:39 EDT 2012

On 2012/09/22, at 21:36, Itamar Turner-Trauring wrote:

> There's three parts to doing this:
>   1. When setting up the portal, in addition to the credential checker
>   that knows about regular users, also register a
>   twisted.cred.checkers.AllowAnonymousAccess.
>   2. When you have no credentials, the xml-rpc layer should login to the
>   portal using a twisted.cred.credentials.Anonymous credential. When you do
>   have credentials, pass them in as you normally.
>   3. Now as part of a login your realm gets either a username, or a
>   twisted.cred.checkers.ANONYMOUS as the avatar id that is being requested.
>   Based on what it gets your realm should return a different business logic
>   implementation (aka "avatar"); the anonymous one can do less, say.

I'm not following why I would want to do #1, probably because I can't find a sufficient explanation of exactly what an "avatar" is supposed to do.  In some places it seems to just be treated as a user ID, and in other places documentation makes reference to "business logic" as you do, but nowhere do I see any examples of what exactly that means. 

It seems to me #1 is overkill; if I want to have methods that don't require authentication (e.g. methods for registering a user in the first place), why would I require all clients to authenticate as anonymous before using them?  It would be a lot simpler to just have my xmlrpc methods check against the attributes of the current user object when called, and then return appropriately: return failures when there is no user, or when the user's attributes don't match those required by the method, and return data that a user's attributes give him/her access to when there is a user.  

But again, I think I'm missing some key details that just aren't in the documentation I've been able to find.

> twisted.web.guard does #2; the way it is implemented, the business logic
> object (avatar) that is returned is a web Resource, so the realm can return
> a different Resource depending on whether there's HTTP credentials or not
> (the latter case being avatar id of ANONYMOUS). It's possible you just want
> to use guard, if you're relying on HTTP authentication - just return
> different XMLRPC objects.

I'm not using HTTP authentication because it requires passing authentication info with each request.  In my design a client can authenticate at any point in the connection to gain access to methods or data that require it.

From your description of Guard it sounds like I would bind a different resource to the factory for each set of permissions a user might have, which means there would be a different Resource defined (and by extension different xmlrpc methods defined) for every possible combination of attributes a user might have.   A user may have a dozen different attributes that go into defining what methods that user can call, or what data will be returned by a method; the combinatorics there could result in thousands of slightly-different Resources and methods I'd need to maintain.

It seems more reasonable to have each xmlrpc method check the current user's attributes and make its own decisions about what data (if any) to return.

> Alternatively, the XMLRPC layer could log-in to
> the portal, in which case it would get back different business logic
> objects with different capabilities.

This sounds like it could be what I'm looking for, but again I can't find anything that discusses in any detail what "business logic" means in this context, or how to implement those different capabilities.

> An example of a full setup is twisted.protocols.ftp combined with
> twisted.tap.ftp, the ftp plugin for twistd, but the details are a bit
> spread out. You should be able to find all three of those parts though.

The FTP protocol doesn't implement any non-authenticated commands.  Authentication is always done at the beginning of a session, even if that is to authenticate as the user 'anonymous', and there's no provision for changing credentials in mid-connection.

I'll have a look anyway though.. perhaps I can piece together a few more things that I haven't been able to find in the API documentation, the twisted.cred how-to, or the cred.py and dbcred.py examples.

I've got a bit further since my initial email, and my current approach is to extend t.w.server.Site to accept a portal.  I'm currently trying to separate the useful bits from the flash in the requestAvatarID and _??Authenticate methods in dbcred.py.  It would be nice to have something as straight-forward as cred.py that also implemented a realm and a credentials checker so that I could see how all those pieces fit together.

Thanks for the info.. hopefully it leads me to piece this stuff together.

More information about the Twisted-Python mailing list