[Zope3-dev] Is someone going to do a LoginManager-alikefor Zoipe3?

Phillip J. Eby pje@telecommunity.com
Thu, 21 Mar 2002 20:40:22 -0500


Wow.  Now I *know* I'm out of date.  I've never seen type assertions in 
interfaces before this message!

This looks pretty well thought out.  I have only a few comments.

First "IAuthenticationService" seems to be a pure data object, with no 
actual *service*.  Shouldn't it just *do* what's laid out in the 
"getPrincipals()" function?  Otherwise it looks like it's just a 
configuration object and shouldn't really exist on its own.

Also, I'm wondering how one distinguishes between output 
principals...  suppose you have both an Anonymous principal and an 
authenticated one?  (But here I'm probably showing my Zope 3 ignorance.)

Something which was useful in Zope 2, but may not be relevant here, was the 
use of a chaining approach within the lists of user sources (identifiers) 
and login methods (extractors).  This allowed one to create login methods 
which could check for additional credentials before granting a 
login.  (E.g., fail if the user wasn't  using SSL.)  I see how one could do 
that with this architecture, but combining such rules requires writing a 
custom "identifier" rather than simply stacking primitives.  Still, I don't 
see a way to create such a chain of responsibility here and still support 
all of the other features this architecture offers.

How are the subjects of logout and credential changes handled?  It's 
unclear to me how one could find one's way to the right credential 
extractors to tell them that credentials (e.g. a user password) was 
changed, or that the user wishes to log out.  I think it would be very good 
if we could address these items, as they commonly required kludging in Zope 
2 without LoginManager.  Under LoginManager, one can say 
AUTHENTICATED_USER.logout(), for example.  What would be the equivalent here?


At 12:36 PM 3/21/02 -0500, Tres Seaver wrote:
>zigg (Matt Behrens) and I had a chat about this today on #zope3-dev.
>What about the following:
>
>   class IAuthenticationService( Interface ):
>
>       def failAnyCredential():
>           " Must all credential extractors approve the request?"
>           return Result( type=Boolean )
>
>       def failAnyPrincipal():
>           " Must all principal identifiers approve the creds?"
>           return Result( type=Boolean )
>
>       def listExtractors():
>           " Return objects which extract credentials from requests. "
>           return Result( type=Sequence( ICredentialsExtractor ) )
>
>       def listIdentifiers():
>           " Return objects which infer principals from credentials."
>           return Result( type=Sequence( IPrincipalIdentifier ) )
>
>       def listChallengers():
>           " Return objects which create authentication challenges."
>           return Result( type=Sequence( IAuthenticationChallenger ) )
>
>   class ICredentialsExtractor( Interface ):
>
>       def extractCredentials( request ):
>           " Return zero or more credentials, plus error or None."
>           request.assertType( IRequest )
>
>           return Result( type=Tuple( Sequence( ICredential ), str ) )
>
>   class IPrincipalIdentifier( Interface ):
>
>       def identifyPrincipals( credentials ):
>           " Return zero or more principals, plus error or None."
>           credentials.assertType( Sequence( ICredential ) )
>
>           return Result( type=Tuple( Sequence( IPrincipal ), str ) )
>
>   class IAuthenticationChallenge( Interface ):
>
>       def challengeAuthentication( request, credentials, principals
>                                  , msg ):
>           " Create an authentication challenge."
>           request.assertType( IRequest )
>           credentials.assertType( Sequence( ICredential ) )
>           principals.assertType( Sequence( IPrincipal ) )
>           msg.assertType( str )
>
>           return Result( type=None )
>
>
>The interaction would then look somethink like:
>
>   def getPrincipals( REQUEST ):
>
>       all_credentials = []
>       for extractor in service.listExtractors():
>           credentials, error = extractor( REQUEST )
>           if error and service.failAnyCredential();
>                raise InvalidCredential, error
>           all_credentials.extend( credentials )
>
>       all_principals = []
>       for identifier in service._principal_identifiers:
>           principals, error = identifier( all_credentials )
>           if error and service.failAnyIdentifier():
>               raise InvalidPrincipal, error
>           all_principals.extend( principals )
>
>       return all_principals
>
>and a different method, wired up to handle authentication
>exceptions, would call the challengers.
>
>Tres.
>--
>===============================================================
>Tres Seaver                                tseaver@zope.com
>Zope Corporation      "Zope Dealers"       http://www.zope.com
>
>
>_______________________________________________
>Zope3-dev mailing list
>Zope3-dev@zope.org
>http://lists.zope.org/mailman/listinfo/zope3-dev