New user authentication and authorisation framework

Dancer::Plugin::Auth::Extensible was released recently, to offer a simple to use yet flexible framework for user authentication and role-based authorisation for Dancer-powered webapps.

Dancer::Plugin::Auth::RBAC was already out there and available, but I never really got on with it, felt it was a little cumbersome to use, and needed a fair amount of work to bring it up to scratch; so, I decided instead to start a new project with the aims of making user authentication (and role-based authorisation, where needed) simple.

So, what makes Dancer::Plugin::Auth::Extensible different?

It's simple

Denoting routes for which the user must be logged in is easy - subroutine attributes are used to indicate that the user must be logged in, or must have a particular role:

get '/secret' => sub :RequireLogin {
    return "User must be logged in to see this.";

post '/user' => sub :RequireRole(Admin) {
    # User must be logged in and have the 'Admin' role in order to hit this
    # route

Simple, eh? The auth framework will deal with ensuring the user is logged in (and has the appropriate role, if you're using roles and the route requires a specific role), and if not, will present them a login page (the framework even provides a basic login page so you can get up and running quickly, but you can of course override that).

For the most simple cases, you might not need roles, simply the requirement that a user be logged in - that's fine, you can disable roles entirely.

Flexible authentication sources

The auth framework plugin ships with a few "authentication provider" classes to authenticate against different sources:

  • Account details in the app's config

    The Config auth provider reads usernames, passwords (preferably crypted) and optionally lists of roles from the app's config. This is a simple and easy way to get started.

  • Account details in a database via Dancer::Plugin::Database

    The Database provider reads usernames, passwords, optionally roles and other details from a database, using Dancer::Plugin::Database.

  • Unix system accounts

    The Unix provider authenticates against Linux/Unix system user accounts; user groups are used for roles, so you can e.g. require a user be in the wheel group, or whatever other user groups you have defined.

  • Accounts in a database, via DBIC

    An auth provider to authenticate against a database using DBIC via Dancer::Plugin::DBIC is coming soon.

If the authentication source you wish to use isn't already supported, it's pretty trivial to write a new authentication provider; they are simply subclasses of Dancer::Plugin::Auth::Extensible::Provider::Base which implement the required methods.

Further providers are planned for e.g. LDAP, IMAP, ActiveDirectory etc.

It's flexible

Multiple authentication realms are supported, so you can configure the framework to, for example, first check a database using the Database provider, then check against an LDAP server (when that provider is available). You can use the same provider in multiple realm configurations, too - for instance, if you needed to check against multiple databases.

Secure password handling is easy

Crypt::SaltedHash is used to handle crypted passwords for you, so it's easy to handle passwords securely (you wouldn't want to be storing passwords in plain text, would you? (I sincerely hope not.))

Convenient keywords are provided

Convenient keywords are provided:

  • logged_in_user

    If the user is logged in, returns a hashref of details about the currently logged-in user. What you get back will depend on the provider in use, but is flexible - for instance, if you're using the Database provider, all columns of the user table will be returned, so if you e.g. have columns containing the user's name and email address, you'll find them here.

  • user_has_role

    Allows you to manually check if the logged-in-user has a role you're interested in - for example:

    if (user_has_role('BeerDrinker')) {
  • user_roles

    Returns a list of the currently logged-in user's roles.

  • authenticate_user

    Usually you'll want to let the built-in login handling code deal with authenticating users, but in case you need to do it yourself, this keyword accepts a username and password, and checks whether they are valid.

Give it a try!

The framework is still new, but is in a state where it's ready to use. If it is of interest to you, have a play with it, and do feel free to submit issues or pull requests on GitHub if you find any issues or would like to suggest new features:


David Precious (BIGPRESH)