PylonsHQ.

Layout: Fixed-width

A Spec for Pylons Auth Packages

Skip to end of metadata
Go to start of metadata

This is a central list of authentication/authorization packages for Pylons, and the desired API for such packages.

Background

(This section written by Mike Orr.)

Pylons needs some kind of flexible but standard system of authentication & authorization. It has also been clear from the past several months that AuthKit provides a unified solution for both issues, but it has not gained sufficient acceptance from the Pylons community to be the standard.

I think it would be in the Pylons tradition to define a minimum spec for authentication and another for authorization, and then let the package authors figure out how to fulfill it and to interoperate with each other; i.e., the WSGI of auth. I have not looked closely at AuthKit or repoze.who yet, but I have to put auth into my own app in a couple weeks. After watching the discussion about the merits of AuthKit vs other stuff, I'm going to stick with my homegrown code because i can get it running quickest. (It was originally written for Quixote and combines LDAP with a local database and group scheme, and authorizes via an omnipotent require_perm("action", **action_kw) function.

But here are my ideas for the general issue:

  • AUTHENTICATION: is more amenable to standardized solutions than authorization because the algorithms are standardized and have a significant amount of boilerplate code. Basic authentication with a local file or db or LDAP or Windows Directory... Add digest + HTTPS to the mix. Form-based authentication for all these data sources. Logout capability, which is problematic with basic authentication. OpenID is another method that has come into vogue.
  • SIMPLE AUTHORIZATION SCHEMES: some sites want blanket protection for the whole site, or for certain sections (i.e., controllers). These cases are pretty standard, but at the same time the code is so small that it doesn't necessarily justify using a library. Conceptually you put a function call in ._before_ or in the base controller's ._call_ or in the action. The function decides if the request is authorized, and calls abort(403) if not. If the user has not logged in, redirect to the login page or abort(401) with a WWW-Authenticate header to force basic authentication.
  • COMPLEX AUTHORIZATION SCHEMES: the authorization may depend on what group the user belongs to or what role s/he has, which database record is being accessed, and what operation the user is attempting. The fundamental result is the same (pass, abort, or redirect) but the decision is complex. These schemes may or may not benefit from a standard authorization library.
  • GROUPS AND ROLES: these can be used to generalize the permission scheme, avoiding the need to set every authorization flag for every user. Without them, we get a user record like this:
    - username
    - password
    - can_view_x?
    - can_view_y?
    - can_modify_y?
    - can_delete_y?
    - can_view_records_in_category_1?

With groups and roles, we get:

    USER:
    - username
    - password
    - belongs to group A
    - also belongs to groups B, C
    - has roles 'author', 'editor', 'admin'

    GROUP or ROLE:
    - group/role ID
    - can_view_x?
    - can_view_y?
    - can_modify_y?

The group/role hierarchy can be simple or arbitrarily complex. A small app might have a flat set of groups with each user in exactly one group. Or in several groups. Groups may be in a linear hierarchy, with each having a superset of the permissions of the previous. Or not. The distinction between groups and roles is fairly arbitrary, but a person is generally in a group (organizational unit) and has roles (kinds of responsibilities).

  • I was hoping to switch my homegrown auth for something more standard, especially since I'm getting calls for finer-grained permission than my linear group hierarchy allows. So a way of organizing groups and roles, and a UI for setting permissions, and some theory about maintaining non-linear hierarchies, is what would most benefit me. I've been impressed with Zope's system in that regard, and the nice table of checkboxes it uses for permission setting. I was considering porting Zope's system when I saw ChrisM had already done it. Although I'm not sure if repoze.who gets into groups/roles; I need to study it more. At first glance it seems to only set REMOTE_USER and punt on the permission schemes.
  • TG2 and Pylons should ideally use the same scheme, or at least compatible schemes. tg.Identity has a good reputation but I hear it hasn't been maintained and is due for replacement? I think I also heard about some Django auth code that might be useful.
  • A chart or list of the various auth packages, showing how well each adheres to the authentication spec and authorization spec (which haven't been written yet), and a summary of its additional features and links to documentation, would be helpful.

Comments on background

Chris AtLee's comments
  • paste's auth_tkt middleware inserts login/logout functions into environ that make it easy for controllers to log a user in or out. I think something like this is an important part of a standard since it means you can change the module that handles authentication persistence between requests.
  • environ[pylonsprojects:"REMOTE_USER"] is a good thing, lets do more stuff like that. paste's auth_tkt middleware also sets environ[pylonsprojects:"REMOTE_USER_DATA"] and environ[pylonsprojects:"REMOTE_USER_TOKENS"]. Could we define certain keys in the environment to contain group and role data? Taking it one step further, could we define keys in the environment that provide functions that test group / role membership?
  • I don't think that the UI for login forms or user administration belong in Pylons itself, it seems more suited to TurboGears. Same for a particular DB schema to manage users, groups and roles.
  • Can Routes be used to manage authorization? I can see how it could be useful to have all the authorization requirements specified in one place instead of scattered across all the controllers.

Quick example of functions that could be in environ

  • environ[pylonsprojects:'pylons.authenticate'](username, password, **extra)
    • Returns a value that indicates if username / password is sufficient to authenticate the user. **extra could be required for two-factor authentication, per-user salts or challenge data. The return value could also contain additional information, such as the reason that authentication failed, group membership data, or internal user ids that should be remembered.
  • environ[pylonsprojects:'pylons.login'](username, **extra)
    • Persists the authentication for the next request. Could save it in a cookie, or session.
  • environ[pylonsprojects:'pylons.logout']()
    • Forgets any stored authentication data for the current user.
  • environ[pylonsprojects:'pylons.authorize'](path)
    • Returns a value that indicates if the user is allowed to access `path` or not.

Spec

(Please add to the draft.)

Authentication

  • Support standard HTTP responses for basic authentication, or manual redirects to a login form, or both.
  • Have backends for one or more of: password file, password db, LDAP, Windows Directory, Open ID, etc.
  • Optional: allow group/role/permission information to be stored in the password db or equivalent.
  • Optional: a UI to browse & set permissions for a user. Zope has a grid of checkboxes which could be ported.
  • Authenticators should set environ[pylonsprojects:"REMOTE_USER"] for the application if the user is logged in.

Authorization

  • require_perm() function or equivalent that calls abort(401) if the user is unauthorized, and issues a redirect and/or sets a HTTP header if the user is not logged in.
  • has_perm() function or equivalent that returns True if the activity would be authorized, or False if not. An index page can use this to generate hyperlinks to permitted pages.

Ian Bicking has wrote a generic WSGI auth proposal bit it has not been officially adopted by the Web-Sig.

Doing it manually

(Put links to Pylons Cookbook articles here.)

Existing software

(List how closely each package is compliant the spec above, any additional features it has, how to interoperate with other auth packages, links to documentation, and download link. Also link to any existing Pylons Cookbook articles that discuss the package.)

repoze.who

Pretty simple and flexible authentication framework. Can be used as a base to write a more specific implementation. Used by default in TurboGears 2.

repoze.what

A fully documented and tested authorization framework. This is the default authorization framework in TurboGears 2.

AuthKit

James Gardner's autothentication and authorization middleware:

WSGIAuth

This is a generic WSGI proposal.

barrel

Luke Arno's authentication WSGI module. Described as "Flexible WSGI authentication and authorization tools."

sentry

Chris AtLee's authentication modules for interfacing with existing authentication systems.

Dalius Dobravolskas' authentication and authorization middlewares

Dalius Dobravolskas' authentication and authorization middlewares:

Ian's auth spec

This is a spec rather than a library, but it should be compared anyway for completeness.

WSGI auth proposal

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Powered by Pylons - Contact Administrators