Purpose The PluggableAuthService is designed to allow incorporation of *any* existing user folder (or related technology), and to make it simple to define project-specific extensions. Theory of Operation The PluggableAuthService defines a framework for a set of plugins which it orchestrates to generate user objects from requests. These user objects implement the "traditional" BasicUser API, and provide additional functionality. Plugin Types PluggableAuthService defines the following plugin types: - Authentication plugins identify the user based on data in the request. o Each PluggableAuthService must contain at least one authentication plugin. o The PluggableAuthService defines an ordered set of authentication plugins, and queries them in order for each request. The first plugin to recognize a user returns the user, or raises an exception (e.g., for password mismatches). If no plugin returns a user, the PluggableAuthService returns an "anonymous" user (which may still have "extended" information added later). - Challenge plugins alter the response to force the user to (re)authenticate, e.g. by redirecting it to a login form, or by setting the protocol-specific headers which initiate the desired challenge. - Decorator plugins add propertysheets to a user, based on request data or on other data sources. o These sources might include application data from the ZODB or from SQL, etc. o They might also pull in user data from LDAP, ActiveDirectory, passwd files, etc. - Group plugins add groups to the list of groups to which the user belongs, using request data or previously-added decorations. - Update plugins write updates back to the data store from which they came (ZODB, SQL, LDAP, etc.) - Validation plugins impose business-specified policies on user properties (particularly on login ID and password). Plugin Registration PluggableAuthService's plugins are configured via its ZMI, or alteratively via an XML import / export mechanism. Each plugin is identified using a TALES path expression, which will be evaluated with an implied 'nocall' modifier; plugins are intended to be callables, with known argument signatures. Request Flow 1. The publisher asks the PluggableAuthService to validate the user's access to a given object:: groups.validate( request, auth, roles ) 2. PluggableAuthService polls its authentication plugins in order, asking each in turn for a user:: for id, plugin in self.listAuthenticationPlugins(): try: user = plugin( request, auth ) except Unauthorized: self.dispatchChallenge( request ) else: user.setAuthenticationSource( id ) break else: user = self.createAnonymousUser() 3. PluggableAuthService allows each of its decorator plugins to annotate the user:: for id, plugin in self.listDecoratorPlugins(): known, schema, data = plugin( user ) if known: sheet = UserPropertySheet( id, schema, **data ) user.addPropertySheet( id, sheet ) 4. PluggableAuthService allows each of its group plugins to assert groups for the user:: for id, plugin in self.listGroupPlugins(): groups = plugin( user ) user.addGroups( groups ) 5. PluggableAuthService returns the annotated / group-ified user to the publisher.