diff -r b6c2b81e49ec -r b3fd91524132 doc/book/en/devrepo/repo/sessions.rst --- 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()) + +