Modular Authentication

September 20, 2010

GravatarBy Michael Snoyman

Dependencies are often a bit of a bind. On the one hand, I want Yesod to be as fully-featured as possible. On the other hand, adding dependencies makes it more difficult to install, especially when those dependencies are system C libraries.

Case in point: Yesod currently has support for OpenID version 1. There is a package providing OpenID 2 support on Hackage, but it introduces a dependency on OpenSSL, which could be difficult for some users to install. (Side point: I can't actually get the package to work; has anyone else had any luck?)

The current approach to authentication hard-codes in all of the possible authentication backends. For the moment, this is OpenID 1, Rpxnow, Facebook and email address. But now I want to support OpenID 2, without changing the Yesod package at all. As it is, this is not possible.

So I'm experimenting with a new, modular authentication framework based upon authentication plugins. The system is very simple: a plugin consists of three pieces:

  • A name.
  • A widget to display on the login screen. For Facebook, this is a "click here to login" link. For OpenID, it's a typical OpenID input field.
  • A dispatch function for handling user requests.

There's a datatype called Creds, as in credentials, and a function called setCreds provided by the new auth module. Plugins simply call setCreds when a user logs in. The application developer determines how to map credentials onto his/her database, and the auth module itself handles the logout page, a status page (useful for Ajax programs) and a login page.

The downside of this new approach is a loss of some type safety: individual plugins cannot have type-safe URLs, but instead must use a [String] to create links. This is definitely a downside, but I think it is a necessary evil to provide the modularity necessary here.

I've created a new branch on github for this code. If you want to take a look, I'd recommend looking at the sample app and the Yesod.Helpers.Auth2 module.

One question: I'm considering separating the entire authentication system into its own package so that its API can change without affecting Yesod version numbers. Any thoughts on that approach? Obviously plugins will be released as their own packages under this new scheme.


comments powered by Disqus