[Zope-dev] Re: [Plone-developers] PAULA: bringing Zope 3's authentication to Plone and beyond

Hermann Himmelbauer dusty at qwer.tk
Wed Jul 16 04:20:58 EDT 2008


Am Mittwoch, 16. Juli 2008 05:48 schrieb Florian Friesdorf:
> On Mon, Jul 14, 2008 at 09:50:25AM +0200, Hermann Himmelbauer wrote:
> > (..)
> > 1) No way to pass PAU-related information to form-code: In PAU, the
> > (..)
> > 2) Lack of documentation: The entities "Principal, InternalPrincipal,
> > PrincipalInfo" are very confusing to a newbie, I still don't get the "big
> > picture".
>
> InternalPrincipal is a persistent object used to store the data of
> principals in a PrincipalFolder, PrincipalInfo is returned upon successfull
> authentication and handed to FoundPrincipalFactory, which extracts some
> information and returns Principal objects.

Ok, this is how I see it, too. But let me describe my understanding more 
specific:

I see it that way that applications with authentication will normally have 
something like a "user" object, which stores all related authentication/user 
information. This user object may reside in a RDB, a text file, or, as here, 
in a PrincipalFolder (as an InternalPrincipal).

If I understand it right, a Principal is an entity that is the result of an 
authentication process and holds all needed information for authorization. 
However, it is not designed to store user specific information, e.g. login 
names, user names and the like.

And PrincipalInfo is somehow a specific aggregation of user data, which can be 
used throughout the application. This object may have to be inherited to an 
extended MyPrincipalInfo object, as many applications may need extra info 
from this object.

So, both the Principal and PrincipalInfo objects have to be created out of the 
user object, it is not possible to create a Principal out of a PrincipalInfo 
and reverse.

Throughout my application, I have the following scenarios:

- I need to display some user data (e.g. in a "logged in" viewlet): I'd use 
PrincipalInfo.
- I need to check for authorization somewhere in my application: I'd use the 
Principal.
- I need to administer the user, e.g. change password etc.: I'd use the user 
object (InternalPrincipal) for that.
- ???

In my application, all I have is the principal (request.principal). So I need 
a viable way to retrieve PrincipalInfo and User/internalPrincipal objects.

How would I do that?

- user object: There seems to be no zope3 support for that yet - so it seems I 
have to do this manually (some getUser(login) function, get the login from 
request.principal.id[lenAUTH_PREFIX):], not very pretty, though.).
- PrincipalInfo: Don't really know - perhaps by somehow getting the PAU object 
and iterating over the authentication modules, calling some getPrincipalInfo 
method?

I personally would favour some adapters, e.g.:

InternalPrincipal = IInternalPrincipal(request)
PrincipalInfo = IPrincipalInfo(request)

The current documentation leaves many of the above points open, or at least, 
did not describe them in a way so that I could understand them.

> > 3) Lack of plugins: No plugin for URL-rewriting, e.g. cookie-less
> > browsers (retrieving auth-information from URL) etc.
>
> I don't know about URL-rewriting, but you should be easily able to write
> your own credentials plugin to extract whatever you like from a request
> object.

Sure it's possible, that's what I did. But it was quite complicated and I had 
to dig very deep into Zope3 code to do that. This is definitely no option for 
a Zope developer who needs to quickly set up a cookie-less application.

> > How excactly should I cache user data so that a single browser request
> > does not lead to multiple RDB queries? And where in the big picture is
> > the "User" entity? (It's probably the InternalPrincipal object, I
> > assume)...
>
> You don't need InternalPrincipal objects, they are specific to
> PrincipalFolder, IMHO.

Well, yes and no - I need some user entity (which is located in the RDB), 
which somehow resembles the InternalPrincipal object.

> I think you need:
> - custom authenticator plugin, that authenticates against RDB and has a
>   dictionary as cache: key = login, value = password;
> - custom foundprinciplefactory, that generates Principal objects from RDB
> data, again using a simple key=login,value=Principal dictionary as cache; -
> eventually a custom credentials plugin, that for your point 3.

That's basically what I did. However, I did not yet implement caching, as some 
things are not yet solved:

- What if the user changes his password? How would the cache update his data?
- What if a user is deleted?

So, it seems there needs to be some method that flushes the cache (e.g. if 
user data changes). Maybe it makes sense to create an extra UserCache utility 
that provides such methods. 

This should be very well laid out before implementing, I think.

Currently, every simple HTTP request leads to 3 select statements on my user 
table (due to authentication, prinipalInfo creation and the like). So, this 
is something that needs to be solved by caching.

> > So I would very, very much suggest to dig into PAU first and fix those
> > shortcomings before porting it to Plone/Zope2.
>
> Exactly what I am doing :)

That's great!
If you have time, please don't forget scenarios, where user data is stored 
outside Zope3 (e.g. RDB). I would very much appreciate, if Zope3 has some 
built in support for that.

Best Regards,
Hermann

-- 
hermann at qwer.tk
GPG key ID: 299893C7 (on keyservers)
FP: 0124 2584 8809 EF2A DBF9  4902 64B4 D16B 2998 93C7


More information about the Zope-Dev mailing list