Authentication and Authorization
Diva includes a simple but flexible subsystem for authentication and authorization. It enables relatively easy switching between HTTP authentication (such as Basic or Digest authentication performed by the web server) and form-based authentication, and provides basic primitives to get started with form-based login, while allowing complete customization. Convenience functions for checking authorization to perform certain actions are provided for use in request handlers and other code.
There's no reliance on a specific backend storage for user profiles and credentials, so applications are responsible for dealing with that. There's also no restriction to a specific method of controlling access to resources (such as ACLs). Applications can use whatever access control granularity they need.
The subsystem does not provide built-in processes and UI for user registration, activation, password resetting, and other high-level features.
The diva.auth module provides an AuthMixIn class that auth-enabled applications are supposed to subclass. It adds a couple of method stubs to Application subclasses, and contributes a request filter that performs authentication.
A concrete application would inherit from AuthMixIn in addition to being derived from Application, and would probably want to implement two methods for handling the domain-specific details of identifying users and controlling their access to certain actions and/or resources. For example:
class MyApp(Application, AuthMixIn): ... def authenticate(self, username, password=None): return User.find(name=username) def is_authorized(self, principal, action=None, resource=None): if action: return action in principal.permissions return True
With HTTP (or “external”) authentication, the actual checking of a users credentials is performed outside of the application code, probably by employing some authentication module at the web server level. In this kind of setup, Diva only reads the result of the authentication process from the REMOTE_USER variable.
With form-based login, the application provides an HTML form that allows the user to enter some kind of identifier and a password. When the form is submitted with valid credentials, a cookie is created that allows the framework to identify the user on subsequent requests.
The framework provides a default form (see FormProcessing), a template, and request handlers for logging in and out. Any of these defaults can be customized or replaced by the application.
Hybrid HTTP/Cookie-based Authentication
This mode allows the use of HTTP authentication without having to protect the entire URL namespace. Only one or more sub-resources (such as /login) are protected by HTTP authentication. When the user visits a protected URL, Diva sets a cookie (in the same manner as with form-based authentication), thereby enabling resources outside of the protected area to identify the user and apply her permissions.
Integration and Utilities
Development Server Integration
As HTTP authentication is generally performed by the web server, testing a web app relying on HTTP authentication is often inconvenient. The Diva DevelopmentServer makes it easy by providing built-in support for HTTP Basic and Digest authentication, which can be configured using command-line options.
Password Management Utilities
The diva.auth module also provides a couple of convenience functions for managing encrypted passwords. These can be useful for applications implementing form-based login, but their use is of course entirely optional.
- Naming: assert_authorized is ugly. ensure_authorized would be better, but still ugly. That the function takes (action, resource) parameters makes it harder to choose a name that “sounds” nice.
See also: Principal.can(action, resource). Not sure about that one, but at least it's short.
- Authorization Decorator: Should there be a request handler decorator form for checking authorization? What should it be called?
- The password encryption utilities are a bit on the silly side. They should either be really useful or get nixed.