Plack::Middleware::Auth::Complex - Feature-rich authentication system


  use Plack::Builder;

  builder {
    enable 'Auth::Complex', dbi_connect => ['dbi:Pg:dbname=mydb', '', ''], mail_from => '';
    sub {
      my ($env) = @_;
      [200, [], ['Hello ' . ($env->{REMOTE_USER} // 'unregistered user')]]


AuthComplex is an authentication system for Plack applications that allows user registration, password changing and password reset.

AuthComplex sets REMOTE_USER if the request includes correct basic authentication and intercepts POST requests to some configurable URLs. It also sets $env->{authcomplex} to itself before passing the request.

Some options can be controlled by passing a hashref to the constructor. More customization can be achieved by subclassing this module.

Intercepted URLs

Only POST requests are intercepted. Parameters can be either query parameters or body parameters. Using query parameters is not recommended. These endpoints return 200 for success, 400 for client error and 500 for server errors. All parameters are mandatory.

POST /action/register?username=user&password=pw&confirm_password=pw&

This URL creates a new user with the given username, password and email. The two passwords must match, the user must match username_regex and the user must not already exist.

POST /action/passwd?password=oldpw&new_password=newpw&confirm_new_password=newpw

This URL changes the password of a user. The user must be authenticated (otherwise the endpoint will return 401).

POST /action/request-reset?username=user

This URL requests a password reset token for the given user. The token will be sent to the user's email address.

A reset token in the default implementation is base64(HMAC-SHA1("$username $passphrase $expiration_unix_time")) . ":$expiration_user_time".

POST /action/reset?username=user&new_password=pw&confirm_new_password=pw&token=token

This URL performs a password reset.

Constructor arguments


Arrayref of arguments to pass to DBI->connect. Defaults to ['dbi:Pg', '', ''].


Data::Entropy::Source object to get random numbers from. By default uses /dev/urandom via Data::Entropy::RawSource::Local if possible, or the default entropy source otherwise. A warning is printed if the default entropy source is used, to supress it set this argument to the default entropy source.


Boolean determining whether to use the scrypt algorithm via the Authen::Passphrase::Scrypt module.

If true, the default implementation of hash_passphrase uses scrypt and check_passphrase accepts scrypt passphrases (in addition to passphrases supported by Authen::Passphrase).

If false, the default implementation of hash_passphrase uses bcrypt and check_passphrase only accepts passphrases supported by Authen::Passphrase.

The default value is true if Authen::Passphrase::Scrypt is installed, false otherwise.


Callback (coderef) that is called just after connecting to the database. Used by the testsuite to create the users table.


SQL statement that selects a user by username. Defaults to 'SELECT id, passphrase, email FROM users WHERE id = ?'.


SQL statement that updates a user's password. Defaults to 'UPDATE users SET passphrase = ? WHERE id = ?'.


SQL statement that inserts a user. Defaults to 'INSERT INTO users (id, passphrase, email) VALUES (?,?,?)'.


HMAC key used for password reset tokens. If not provided it is generated randomly, in which case reset tokens do not persist across application restarts.


From: header of password reset emails. If not provided, password reset is disabled.


The subject of password reset emails. Defaults to 'Password reset token'.


Authentication realm. Defaults to 'restricted area'.


If true, all authentication results are cached. If false, only successful logins are cached. Defaults to false.


Authentication cache timeout, in seconds. Authentication results are cached for this number of seconds to avoid expensive hashing. Defaults to 5 minutes.


Password reset token validity, in seconds. Defaults to 1 hour.


Regular expression that matches valid usernames. Defaults to qr/^\w{2,20}$/as.


Error message returned when the username does not match username_regex. Defaults to 'Invalid username'


URL for registering. Defaults to '/action/register'.


URL for changing your password. Defaults to '/action/passwd'.


URL for requesting a password reset token by email. Defaults to '/action/request-reset'.


URL for resetting your password with a reset token. Defaults to '/action/reset'.



Returns a list of default options for the constructor.


Creates a new AuthComplex object.


Called when the first request is received. The default implementation connects to the database, calls post_connect_cb and prepares the SQL statements.


Inserts a new user into the database. $parms is a Hash::MultiValue object containing the request parameters.


Returns a hashref with (at least) the following keys: passphrase (the RFC2307-formatted passphrase of the user), email (the user's email address).

check_passphrase($username, $passphrase)

Returns true if the given plaintext passphrase matches the one obtained from database. Default implementation uses Authen::Passphrase (and Authen::Passphrase::Scrypt if use_scrypt is true).


Returns a RFC2307-formatted hash of the passphrase.

If use_scrypt is true, default implementation uses Authen::Passphrase::Scrypt with default parameters.

If use_scrypt is false, default implementation uses Authen::Passphrase::BlowfishCrypt with a cost of 10 and a random salt.

set_passphrase($username, $passphrase)

Changes a user's passphrase to the given value.

make_reset_hmac($username, [@data])

Returns the HMAC part of the reset token.

mail_body($username, $token)

Returns the body of the password reset email for the given username and password reset token.


Generates a new reset token and sends it to the user via email.

response($code, $body)

Helper method. Returns a PSGI response with the given response code and string body.


Shorthand for response(200, $message).


Shorthand for response(400, $message).


Shorthand for response(500, $message).


Returns a 401 Authorization required response.


Handles the /action/register endpoint. $req is a Plack::Request object.


Handles the /action/passwd endpoint. $req is a Plack::Request object.


Handles the /action/request-reset endpoint. $req is a Plack::Request object.


Handles the /action/reset endpoint. $req is a Plack::Request object.


Marius Gavrilescu, <>


Copyright (C) 2015-2017 by Marius Gavrilescu

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.20.1 or, at your option, any later version of Perl 5 you may have available.