The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Plack::Middleware::DoormanAuthentication - The generic authentication middleware.

SYNOPSIS

    use Plack::Request;
    use Plack::Builder;

    builder {
        enable "Session";
        enable "DoormanAuthentication", authenticator => sub {
            my ($self, $env) = @_;
            my $request = Plack::Request->new($env);
            return $request->param("username")
                if $request->param("username") eq "john" && $request->param("password") eq "secret";
        };

        sub {
            my $env = shift;
            my $doorman = $env->{'doorman.users.authentication'};
            my $current_username = $doorman->is_sign_in;

            ...
        }
    };

DESCRIPTION

This middleware is for doing generic authentication. In other words, it does not do the real authenticate at all, but merely just keep the authentication info that your (the developer) provide from the authenticator callback in the session.

OPTIONS

  • authenticator

    This setting is mandatory, and it must be a CODEref callback that will be called once this middleware need to do the real authentication work.

    Here's an simple example that only authenticate "john" with correct password:

        enable "DoormanAuthentication", authenticator => sub {
            my ($self, $env) = @_;
            my $request = Plack::Request->new($env);
            return $request->param("username")
                if $request->param("username") eq "john" && $request->param("password") eq "secret";
        };

    The authenticator callback is called as a method of an instance of this middleware class, with the PSGI $env hash as its sole method parameter. For most web apps the authenticator checks certain form fields like the examples above. If the authenticator is based on request headers but not only form fields, it is still feasible by building a Plack::Request object from $env.

    The authenticator callback should return a false value (0 or undef) when the sign-in request is not considered successful (eg, wrong password). It should return an id of some sort for your app code to latter retrieve user information from database. A numerical id or username might work.

    The returned value of the authenticator callback is kept in the session and used to decide if current session is considered signed in.

  • scope

    This setting is optional with default value "users", and useful if you need multiple roles to login in to your system.

    For example, if you need "users" and "admins" roles to have different login session, you can achieve it by:

        enable "DoormanAuthentication", scope => "users";
        enable "DoormanAuthentication", scope => "admins";

    For each scope, a path named after that scope is taken by DoormanAuthentication middleware as the end-points to perforam openid login.

    By default, the following paths and HTTP methods are responded by this middleware:

        POST /users/sign_in
        GET  /users/sign_out
        GET  /users/openid_verified

    For the "admins" scope, it'll add:

        POST /admins/sign_in
        GET  /admins/sign_out
        GET  /admins/openid_verified

METHODS

  • sign_in_path, sign_in_url

    Returns a path, or full url, that is used to let user POST an openid url to sign in. It should be used as the value of "action" attribute of a form. For example, like in this form:

        my $doorman = $env->{'doorman.users.authentication'};
    
        my $sign_in_form = <<HTML5;
        <form method="POST" action="@{[ $doorman->sign_in_path ]}">
          <p>
            <label>Username</label>
            <input type="text" name="username" autofocus>
          </p>
          <p>
            <label>Password</label>
            <input type="password" name="password">
          </p>
          <p>
            <input type="submit" value="Sign In">
          </p>
        </form>
        HTML5

    The form uses username and password as the name of the fields. Accordingly, the authenticator callback should be coded to authenticate users by those values. In other words, you must choose the field names that will be used to authenticate, and you need to properly code HTML and authenticator callback to put them together.

  • is_sign_in

    Returns true if the current session is considered signed in.

    In fact, it returns the return value of the authenticator callback. It is recommended that your authenticator callback returns a primary key to the authenticated user, and use that value to retrieve the user object from whatever backend database you use:

        my $app = sub {
            my $env = shift;
            my $doorman = $env->{'doorman.users.authentication'};
    
            my $current_user = MyModel::User->load( $doorman->is_sign_in );
    
            ...
        };
  • sign_out_path, sign_out_url

    Returns a path that, when visited (GET), wipes out the signed in information from the session.