OpenID Passurl
Perhaps the simplest way of handling authentication in your application is to
use OpenID. With OpenID the user enters their identity URL and the middleware
contacts the identity provider associated with the URL. The identity provider
then handles the authentication and replies to tell the middleware if the user
is signed in. The middleware then sets a cookie and redirects the user to the
specified URL now that they are signed in.
To set up passurl support you can specify the following in a config file:
authkit.setup.method = openid, cookie
authkit.cookie.secret = some secret phrase
You can also specify the template you wish to use and there are three ways to
do this. The first is to specify the openid_template option with the new
template. The template should contain the variables $action, $message,
$css_class and $value which will be replaced with appropriate values
by AuthKit. On Python 2.4 you can use any syntax supported by the
string.Template class, on previous versions the strings are substituted
directly. Here is an example:
openid_template = """\
<html>
<head><title>Please Sign In</title></head>
<body>
<h1>Please Sign In</h1>
<div class="$css_class">$message</div>
<form action="$action" method="post">
<dl>
<dt>Passurl:</dt>
<dd><input type="text" name="passurl" value="$value"></dd>
</dl>
<input type="submit" name="authform" />
<hr />
</form>
</body>
</html>
"""
You can also specify openid_template_file which should be a file
containing the template with the same variables described above or
openid_template_obj which should be the paste path to a string object in
an existing module or a callable which returns the template string. For
example:
authkit.openid.template.obj = authkit.authenticate.open_id:template
The OpenID support sets a cookie once the user is signed in. This cookie
takes all the options described in the "Cookie Options" section which are
incidentally the same as for form authentication or forward authentication.
Remember that if you specify cookie_signoutpath the cookie will be removed but if
you do not handle the path in the application the user is likely to be shown a
"404 Not Found" page. See the documentation about the forward section for a
description of this.
In addition you can specify the following options which define the paths that
the openid middleware will react to. If you don't specify them appropriate
defaults will be used but you must be aware that the middleware will intercept
these paths for its own processing so the requests at these paths won't be
passed on to your application. For example:
authkit.openid.path.verify = /verify
authkit.openid.path.process = /process
authkit.openid.path.signedin = /account/just_signedin
The openid_path_signedin variable is required and is the URL that the user
should be redirected to after a successful sign in.
You should also specify the base URL for the application so that the identity
provider can be redirected to the correct place. This is provided because it is
common to need a different external base URL to the one at which the app is
actually running, for example if you are running behind a load balancer or
using Apache mod_rewrite, or mounting the app at a non-root URL. If you don't
specify a base URL it will be calculated automatically from the environment.
The baseurl should not have a trailing /:
authkit.openid.baseurl = http://localhost:5000
Warning
If you are getting errors when using the openid method you should set
a base URL as it is possible that one of the redirects is going to the
wrong place.
You can also specify a function to convert a URL to a username. If you don't
specify a function, REMOTE_USER is set to the identity URL of the user.
You can specify the function like this:
authkit.openid.urltouser = authkit.authenticate.open_id:openid_urltouser
The function should take the format below:
def passurl_urltouser(environ, url):
# Convert the URL to a username here
...
return username
Unlike the forward and form methods, there is no signin option yet
to specify a URL where the user can sign in. Although this may be added. Just
return a 401 response in your application to have the sign in page shown.
The openid middleware also needs a store. The only stores supported so far are
mysql or file. You specify the store type with the openid_store_type
option. If you use MySQL, then passurl_store_config is required and should be
a database URI in the format used by SQLAlchemy. If you are using a file store then
openid_store_config should specify the path to use. File stores don't work on
Windows. MySQL stores also require the MySQLdb module to be installed manually.
The installation of this module depends on your platform. You will also need to
install the following:
easy_install "DBUtils>=0.9.2"
easy_install "SQLAlchemy>=0.3.2"
Finally, openid support requires a session to be present. The assumed default is
that you are using beaker:
easy_install beaker
If you are using beaker it will be setup for you without any further
configuration. Otherwise you must setup any other session middleware yourself
such that there exists in environ a session object accessible via the key
specified in passurl.session.middleware. The session object in the environ
should have the following properties:
environ[session_key].save() - saves the session
environ[session_key][key] = value - should set the key ``key`` to the value ``value``
environ[session_key].id - should return the unique ID of the session
If these conditions are matched then your session code is compatible with AuthKit's
openid middleware support.
The session should also be given a secret to help prevent anyone guessing it with
openid_session_secret and can be given a different key with
openid_session_key to enable you to use the beaker session middleware with lots
of different applications. The default is authkit_openid which is
unlikely to conflict with anything else. This means you can use OpenID passurl
support with Pylons which already has the beaker session setup. For example:
authkit.openid.session.middleware = beaker.session
authkit.openid.session.key = authkit_openid
authkit.openid.session.secret = random string
Here is a full example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | from authkit.authenticate import middleware, sample_app
app = middleware(
sample_app,
setup_method='passurl,cookie',
passurl_path_signedin='/private',
passurl_store_type='file',
passurl_store_config='',
cookie_secret='secret encryption string',
cookie_signoutpath = '/signout',
)
if __name__ == '__main__':
from paste.httpserver import serve
serve(app, host='0.0.0.0', port=8080)
|
If you want to test this example, feel free to create an account on passurl.com
which is currently in alpha. The accounts will be cleared before launch so it is
a good time to use them for testing. Please report any problems you find too!
Note
"Passurl" is a trademark of James Gardner
I had to install ElementTree otherwise OpenId library didn't work.