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

Tres Seaver tseaver@zope.com
21 Mar 2002 12:36:36 -0500


On Wed, 2002-03-20 at 21:30, Phillip J. Eby wrote:
> At 11:47 AM 3/14/02 -0500, Jim Fulton wrote:
> >"Phillip J. Eby" wrote:
> > >
> > > At 05:58 PM 3/12/02 -0500, Jim Fulton wrote:
> > >
> > > >I thought someone was talking about that, but I don't remember
> > > >who?
> > >
> > > Well, Ty and I will almost certainly need one at some point, and if there
> > > isn't one, we'll write one.  :)
> > >
> > > The tricky bit is that our group just lost two developers, making it likely
> > > that "some point" is a later point in time than it was before.  :(
> >
> >Wanna take a shot at documenting a Zope3-based design? Maybe expressed
> >as some interfaces and simple collaborations? We could get the implementation
> >done by others, perhaps in an upcoming sprint.
> 
> I'd be happy to...  *but* I'll need a little help getting re-oriented to 
> Z3.  I haven't been following Zope 3's evolution closely lately, and don't 
> even know where to look for the interfaces that the auth service should be 
> following.
> 
> What does Z3 want from an auth service?  Is there some place you can point 
> me to for the current docs on principals, etc.  I need to know what 
> architecture this has to fit into, if you see what I mean.  I'd be willing 
> to draw up the interfaces, and maybe even contribute the core algorithm and 
> one or two trivial auth pieces (e.g. Basic, REMOTE_USER) and a trivial user 
> source (e.g. an "Anonymous" one, and maybe a .zcml-based one.)  Assuming, 
> of course, there aren't already suitable sources for Principals in Z3 now; 
> as I said, I've had other things to attend to.  :(

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