--- 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())
+
+