PylonsHQ.

Layout: Fixed-width

Authentication and Authorization with `repoze.who`

Skip to end of metadata
Go to start of metadata

Overview

``repoze.who`` is an identification and authentication framework
for arbitrary WSGI applications. It acts as WSGI middleware.

``repoze.who`` is inspired by Zope 2's Pluggable Authentication
Service (PAS) (but ``repoze.who`` is not dependent on Zope in any
way; it is useful for any WSGI application). It provides no
facility for authorization (ensuring whether a user can or cannot
perform the operation implied by the request). This is considered
to be the domain of the WSGI application.

It attemtps to reuse implementations from ``paste.auth`` for some
of its functionality.

This page shows how to use repoze.who with your Pylons project.

Another tutorial on repoze.who with Pylons is at http://truefalsemaybe.com/2008/06/authorization-in-pylons-with-repozewho-part-1-htaccess/

Getting `repoze.who`

`repoze.who`, as most python packages, can be installed via easy_install. To do that, run the following command:

easy_install -i http://dist.repoze.org/who/latest/simple repoze.who

The official release notes can be found on the Repoze Blog.

Adding `repoze.who` to your Pylons project

Useful Information
From here on forth, when referring to files, the following constants shall be used:
  • PRJ - the name of your project.
  • ROOT - the root directory of your project (has development.ini, test.ini, etc).

Open up ROOT/development.ini and append the following lines to the [app:main] section:

who.config_file = %(here)s/who.ini
who.log_level = debug
who.log_file = stdout

Now, open ROOT/PRJ/config/middleware.py.
Add the following line to the top of the file:

from repoze.who.config import make_middleware_with_config as make_who_with_config

After the comment "CUSTOM MIDDLEWARE HERE" add the following line:

app = make_who_with_config(app, global_conf, app_conf['who.config_file'], app_conf['who.log_file'], app_conf['who.log_level'])

That's it. You now have `repoze.who` integrated to your project.

Setting up `repoze.who`

Create the file ROOT/who.ini.
This file will host your `repoze.who` configuration. You can see the example configuration provided in the repoze.who documentation.

As an additional example the following can be used:

ROOT/who.ini

[plugin:form]
use = repoze.who.plugins.form:make_redirecting_plugin
login_form_url = /account/login
login_handler_path = /account/dologin
logout_handler_path = /account/logout
rememberer_name = auth_tkt

[plugin:auth_tkt]
use = repoze.who.plugins.auth_tkt:make_plugin
secret = [INSERT SECRET HERE]

[general]
request_classifier = repoze.who.classifiers:default_request_classifier
challenge_decider = repoze.who.classifiers:default_challenge_decider

[identifiers]
plugins =
    form;browser
    auth_tkt

[authenticators]
plugins =
        PRJ.lib.auth.repoze_auth:UserModelPlugin

[challengers]
plugins =
    form;browser

[mdproviders]
plugins =
        PRJ.lib.auth.repoze_auth:UserModelPlugin

The example above uses a custom form for logging in, so the redirecting form plugin was used.
It also uses a custom class that checks if the given user data is correct from the database.

Example of a custom `repoze.who` plugin

The previous configuration used a UserModelPlugin to verify the users against a database and retrieve information about the user from the database.

ROOT/PRJ/lib/auth/repoze_auth.py

from paste.httpexceptions import HTTPFound
from PRJ import model

class UserModelPlugin(object):
    
    def authenticate(self, environ, identity):
        try:
            username = identity['login']
            password = identity['password']
        except KeyError:
            return None
        
        success = model.User.authenticate(username, password)
        
        return success

    def add_metadata(self, environ, identity):
        username = identity.get('repoze.who.userid')
        user = model.User.get(username)
        
        if user is not None:
            identity['user'] = user

Using `repoze.who` in your code (by example)

Example #1

...

# Get the `repoze.who` identity object. (Only available if a user is logged in.)
identity = environ.get('repoze.who.identity')

if identity is not None:
    # Get some data associated with the user. (Eg. the user object that was assigned in UserModelPlugin.)
    user = identity.get('user')

...

Example #2

...

if notAuthenticated:
    abort(401, 'You are not authenticated')

if isForbidden:
    abort(403, 'You don\'t have rights to access this page')

...

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jan 16, 2010

    Jamie Begin says:

    ImportError: No module named auth.repoze_auth If you're getting this error, 1)...

    ImportError: No module named auth.repoze_auth

    If you're getting this error, 1) make sure that you've created the example plugin file "repoze_auth.py" as described towards the end of the HOWTO and 2) create an empty file named "__init__.py" in your "lib/auth" directory.

  2. Jun 14, 2010

    Alexander Stanley says:

    If you want 'identity' to be a part of every controller then you should edit PRJ...

    If you want 'identity' to be a part of every controller then you should edit PRJ/lib/base.py so that

    self.identity = environ.get('repoze.who.identity')

    is directly before

    return WSGIController._call_(self, environ, start_response)

    at the same indentation.

    This saves a bit of time/frustration later.

  3. Feb 26, 2011

    Vincent Catalano says:

    I'm still confused on how the actual authentication occurs using a form post and...

    I'm still confused on how the actual authentication occurs using a form post and the application. You're repoze_auth.py does nothing to explain how this is accomplished. What takes place in your authenticate method for User?


Powered by Pylons - Contact Administrators