Ticket #210 (closed enhancement: fixed)

Opened 3 months ago

Last modified 2 months ago

AuthKit

Reported by: pvalsecc Assigned to: fredj
Priority: blocker Milestone: 1.0 Release
Component: General.server Version: SVN
Keywords: Cc:
State: Commit

Description (Last modified by sypasche)

I did some experimenting with authentication using AuthKit.

First, to make it work with the versions of python libraries MapFish is using, you need to patch a few things:

  • the SVN revision 156 of AuthKit, patched with AuthKitMapFish.patch
  • the version 1.9.2 of Routes, patched with RoutesMapFish.patch
  • add a few things to MapFish with the patch MapFishAuthentication.patch

Then, you have to add that to your .ini file:

# AuthKit configuration ===============================================

# choose if you want Form or OpenId athentication
authkit.setup.method = form, cookie
#authkit.setup.method = openid, cookie

# choose between the cached version or the normal version
#authkit.openid.authenticate.user.type = authkit.users.sqlalchemy_driver:UsersFromDatabase
#authkit.form.authenticate.user.type = authkit.users.sqlalchemy_driver:UsersFromDatabase
authkit.openid.authenticate.user.type = mapfish.lib.user_auth:CachedUsersFromDatabase
authkit.form.authenticate.user.type = mapfish.lib.user_auth:CachedUsersFromDatabase

# General configuration
# TODO: we should generate a random secret here
authkit.cookie.secret = xxxxxxxxx
authkit.cookie.signoutpath = /logout
authkit.cookie.name = myproject-auth
authkit.cookie.includeip = True

# OpenId configuration
authkit.openid.store.type = file
authkit.openid.store.config = %(here)s/data
authkit.openid.urltouser = authkit.authenticate.open_id:passurl_urltouser
authkit.openid.path.signedin = /about
authkit.openid.authenticate.user.encrypt = authkit.users:md5
# TODO: we should generate a random secret here
authkit.openid.authenticate.user.encrypt.secret = xxxxxxx
authkit.openid.authenticate.user.data = myproject.model
authkit.openid.template.obj = myproject.lib.template:make_openid_template

# Form configuration
authkit.form.authenticate.user.encrypt = authkit.users:md5
# TODO: we should generate a random secret here
authkit.form.authenticate.user.encrypt.secret = xxxxxxxxxx
authkit.form.authenticate.user.data = myproject.model
authkit.form.template.obj = myproject.lib.template:make_template

The template for the authentication must be provided by two function in myproject.lib.template:

import pylons
from pylons.templating import Buffet
from pylons import config
import myproject.lib.helpers as h

class MyBuffet(Buffet):
    def _update_names(self, ns):
        return ns

def_eng = config['buffet.template_engines'][0]
buffet = MyBuffet(
    def_eng['engine'],
    template_root=def_eng['template_root'],
    **def_eng['template_options']
)

for e in config['buffet.template_engines'][1:]:
    buffet.prepare(
        e['engine'],
        template_root=e['template_root'],
        alias=e['alias'],
        **e['template_options']
    )

class State:
    pass

c = State()
c.user = 'None'

def make_template():
    return buffet.render(
        template_name="/signin.mako",
        namespace=dict(h=h, c=State())
    ).replace("%", "%%").replace("FORM_ACTION", "%s")

def make_openid_template():
    return buffet.render(
        template_name="/openid.mako",
        namespace=dict(h=h, c=State())
    ).replace("%", "%%")

Then, from a Paster shell, you can update your database to add some rights:

from unhcr import model
model.meta.create_all()

users=request.environ['authkit.users']
users.user_create('demo', 'demo')
users.user_create('viewuser',  'viewuser')
users.user_create('edituser',  'edituser')
users.role_create('view')
users.role_create('edit')
users.user_add_role('viewuser', 'view')
users.user_add_role('edituser', 'view')
users.user_add_role('edituser', 'edit')
model.meta.Session.commit()

Now, you can use the mapfish.controller.AuthProxy to protect WMS servers and use AuthKit's permissions to protect controllers' actions like that:

    from authkit.authorize.pylons_adaptors import authorize
    from authkit.permissions import ValidAuthKitUser
    [...]
    @authorize(ValidAuthKitUser())
    def index(self):
        return render('/index.mako')

Attachments

MapFishAuthentication.patch (11.2 kB) - added by pvalsecc on 08/19/08 10:37:10.
The patch for Map Fish?
RoutesMapFish.patch (0.5 kB) - added by pvalsecc on 08/19/08 10:37:53.
The patch for Routes v1.9.2
AuthKitMapFish.patch (6.2 kB) - added by pvalsecc on 08/19/08 10:38:19.
The patch for AuthKit
MapFishAuthentication_v2.patch (13.2 kB) - added by sypasche on 08/26/08 09:58:18.
version 2
security_server_patch_2.diff (49.7 kB) - added by sypasche on 08/29/08 11:29:21.
for review

Change History

08/19/08 10:37:10 changed by pvalsecc

  • attachment MapFishAuthentication.patch added.

The patch for Map Fish?

08/19/08 10:37:53 changed by pvalsecc

  • attachment RoutesMapFish.patch added.

The patch for Routes v1.9.2

08/19/08 10:38:19 changed by pvalsecc

  • attachment AuthKitMapFish.patch added.

The patch for AuthKit

08/19/08 10:43:58 changed by pvalsecc

I forgot to add a few stuff...

You have to change your middleware like that:

if asbool(full_stack):
        # Handle Python exceptions
        app = ErrorHandler(app, global_conf, error_template=error_template,
                           **config['pylons.errorware'])

        # AuthKit authentication
        import authkit.authenticate
        app = authkit.authenticate.middleware(app, app_conf)
        from beaker.middleware import SessionMiddleware
        app = SessionMiddleware(app, {})

        # Display error documents for 401, 403, 404 status codes (and
        # 500 when debug is disabled)
        app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf)

You have to add that at the end of your myproject.model.__init__.py:

meta = MetaData(config['pylons.g'].sa_unhcr_webgis_engine)
meta.Session = Session

08/19/08 17:17:43 changed by sypasche

  • description changed.

08/19/08 17:18:10 changed by sypasche

  • description changed.

08/22/08 10:54:24 changed by sypasche

  • description changed.

08/22/08 11:35:34 changed by sypasche

Small change to do in the Map Fish Authentication?.patch: s/auth_proxy.addRoutes/auth_proxy.add_routes/ in the documentation

08/26/08 09:58:18 changed by sypasche

  • attachment MapFishAuthentication_v2.patch added.

version 2

08/26/08 10:07:05 changed by sypasche

This new version adds support for exporting the permissions as JSON (to be used by the client to modify the UI according to the permissions).

For the AuthProxyController controller, it is possible to use multiple WMS servers. Here's an example controller with configuration:

class WmsAuthProxyController(AuthProxyController):
    def __init__(self):
        layers = []
        layers.append(WMSLayer(alias="c2corg",
                               url="http://demo.mapfish.org/mapfishsample/trunk/wms",
                               layers={
                                       "summits": HasAuthKitRole('view'),
                                       "DEFAULT": Deny()
                               }))
        layers.append(TileCacheLayer(alias="tilecache",
                                     url="http://example.com/tilecache/",
                                     layers={
                                             "background": HasAuthKitRole('view'),
                                             "camp_mapserver": HasAuthKitRole('view')
                                     }))
        self.set_layers(layers)
 

A new controller, SecurityController is used to publish permissions to the client. It will read the permission options from a <packagename>/config/permissions.py python file, here's an example:

from authkit.permissions import HasAuthKitRole, ValidAuthKitUser
from mapfish.controllers.security import Deny

permissions = {
    "application": ValidAuthKitUser(),
    "application.widgets.edit": HasAuthKitRole("editor"),
    "widgets.print.dpi.100": Deny()
}

It will also call the get_permissions method on each of the controllers so that they can provide module specific permissions. The controller then computes permissions according to the user's roles and then return them as JSON.

The client part is not implemented yet. Some things need to be completed and tests added.

08/29/08 11:29:21 changed by sypasche

  • attachment security_server_patch_2.diff added.

for review

08/29/08 11:30:54 changed by sypasche

  • state changed from Needs discussion to Review.

Last patch content: New auth_proxy (based on Patrick's version) and security controllers. user_auth AuthKit module (by Patrick). new Pylons testapp application for unit testing the MapFish Pylons controllers (with tests for auth_proxy and security controllers).

Please review.

08/29/08 11:41:46 changed by sypasche

Just to note that if you are using the user name/password/roles declared inside the project .ini file, you can use Auht Kit? 0.4 and don't need to patch Routes or Auth Kit?.

08/29/08 12:03:26 changed by sypasche

I had some issues with empty files. Do this for creating them:

mkdir -p ./server/python/testapp/testapp/model/
touch ./server/python/testapp/testapp/model/__init__.py \
      ./server/python/testapp/testapp/__init__.py \
      ./server/python/testapp/testapp/controllers/__init__.py \
      ./server/python/testapp/testapp/tests/functional/__init__.py \
      ./server/python/testapp/testapp/tests/test_models.py \
      ./server/python/testapp/testapp/config/__init__.py \
      ./server/python/testapp/testapp/lib/__init__.py

09/01/08 17:02:11 changed by elemoine

  • state changed from Review to Commit.
  • milestone set to 0.3 Release.

Let's not include the Cached Users From Database? class in the patch, as this one can be used only if Routes and AuthKit are patched (with Patrick's patches). The rest looks good, please commit.

09/02/08 10:17:01 changed by sypasche

  • status changed from new to closed.
  • resolution set to fixed.

(In [959]) New auth_proxy (based on Patrick's version) and security controllers. new Pylons testapp application for unit testing the Map Fish? Pylons controllers (with tests for auth_proxy and security controllers). r=elemoine (closes #210)

09/17/08 14:55:26 changed by elemoine

  • milestone changed from 0.3 Release to 1.0 Release.