doc/book/en/devrepo/repo/sessions.rst
branchstable
changeset 6313 b3fd91524132
parent 6311 afd6a9e45489
child 6319 20a7399ed58d
--- a/doc/book/en/devrepo/repo/sessions.rst	Wed Sep 22 19:44:37 2010 +0200
+++ b/doc/book/en/devrepo/repo/sessions.rst	Wed Sep 22 20:12:38 2010 +0200
@@ -30,6 +30,7 @@
 to be used like this:
 
 .. sourcecode:: python
+
    session = self.repo.internal_session()
    try:
        # do stuff
@@ -46,7 +47,7 @@
 The authentication process is a ballet involving a few dancers:
 
 * through its `connect` method the top-level application object (the
-  `CubicWebPublisher`) will (re-)open a session whenever a web request
+  `CubicWebPublisher`) will open a session whenever a web request
   comes in; it asks the `session manager` to open a session (giving
   the web request object as context) using `open_session`
 
@@ -73,8 +74,62 @@
         from which a regular `Session` object is made; it returns the
         session id
 
+        * the source in turn will defer work to an authentifier class
+          that define the ultimate `authenticate` method (for instance
+          the native source will query the database against the
+          provided credentials)
+
     * the authentication manager, on success, will call back _all_
       retrievers with `authenticated` and return its authentication
       data (on failure, it will try the anonymous login or, if the
       configuration forbids it, raise an `AuthenticationError`)
 
+Writing authentication plugins
+------------------------------
+
+Sometimes CubicWeb's out-of-the-box authentication schemes (cookie and
+http) are not sufficient. Nowadays there is a plethore of such schemes
+and the framework cannot provide them all, but as the sequence above
+may show, it is extensible.
+
+Two levels have to be considered when writing an authentication
+plugin: the web client the repository.
+
+On the repository side, it is possible to register a source
+authentifier using the following kind of code:
+
+.. sourcecode:: python
+
+ from cubicweb.server.sources import native
+
+ class FooAuthentifier(native.BaseAuthentifier):
+     """ a source authentifier plugin
+     if the password is 'foo', it's ok
+     """
+     auth_rql = ('Any X,P WHERE X is CWUser, X login %(login)s, X upassword P')
+
+     def authenticate(self, session, login, **kwargs):
+         """return CWUser eid for the given login
+         if this account is defined in this source,
+         else raise `AuthenticationError`
+         """
+         session.debug('authentication by %s', self.__class__.__name__)
+         try:
+             rset = session.execute(self.auth_rql, {'login': login})
+             if rset[0][1].lower() == u'foo':
+                 return rset[0][0]
+         except Exception, exc:
+             session.debug('authentication failure (%s)', exc)
+             pass
+         raise AuthenticationError('user password is not foo')
+
+ class ServerStartupHook(hook.Hook):
+     """ register the foo authenticator """
+     __regid__ = 'fooauthenticatorregisterer'
+     events = ('server_startup',)
+
+     def __call__(self):
+         self.debug('registering foo authentifier')
+         self.repo.system_source.add_authentifier(FooAuthentifier())
+
+