NAME
    Maypole::Plugin::Authentication::Abstract - Abstract Authentication for
    Maypole

SYNOPSIS
    Simple example of all three security levels:

        use Maypole::Application qw(Authentication::Abstract);

        sub authenticate {
            my $r = shift;
            if ( $r->table eq 'openforall' ) {
                $r->public;
            }
            elsif ( $r->table eq 'membersonly' ) {
                $r->private;
                $r->template('login') unless $r->user;
            }
            elsif ( $r->table eq 'topsecret' ) {
                $r->restricted;
                $r->template('login') unless $r->user;
            }
            return OK;
        }

        [% session %]
        [% session_id %]
        [% ticket %]

    Another example:

        use Maypole::Application qw(Authentication::Abstract);

        MyApp->config->auth(
            user_class    => 'MyApp::Customer',
            user_field    => 'email',
            session_class => 'Apache::Session::Postgres',
            session_args  => {
                DataSource => 'dbi:Pg:dbname=myapp',
                UserName   => 'postgres',
                Password   => '',
                Commit     => 1
            }
        );

        sub authenticate {
            my $r = shift;
            if ( $r->table eq 'products' && $r->action eq 'list' ) {
                $r->public;
            }
            elsif ( $r->table eq 'products' && $r->action eq 'search' ) {
                $r->private;
                $r->template('login') unless $r->user;
            }
            elsif ( $r->table eq 'products' && $r->action eq 'edit' ) {
                $r->restricted;
                $r->template('login') unless $r->user;
            }
            return OK;
        }

    With exceptions:

        use Maypole::Application qw(Authentication::Abstract);
        use Exception::Class
          LoginException   => { description => 'Login failed' },
          SessionException => { description => 'Session initialization failed' };

        MyApp->config->login_exception('LoginException');
        MyApp->config->session_exception('SessionException');

        sub authenticate {
            my $r = shift;
            if ( $r->table eq 'openforall' ) {
                $r->public;
                return OK;
            }
            elsif ( $r->table eq 'membersonly' ) {
                $r->private;
                $r->template('login') unless $r->user;
                return OK;
            }
            elsif ( $r->table eq 'topsecret' ) {
                $r->restricted;
                $r->template('login') unless $r->user;
                return OK;
            }
            return DECLINED;
        }

        sub exception {
            my ( $r, $e ) = @_;
            if ( $e->isa('LoginException') ) {
                warn "Login failed: $e";
                # Do something to correct the failure
                return OK;
            }
            elsif ( $e->isa('SessionException') ) {
                warn "Session initialization failed: $e";
                # Do something to correct the failure
                return OK;
            }
            return ERROR;
        }

    Tickets in templates

        <INPUT TYPE="hidden" NAME="ticket" VALUE="[% ticket %]">

    Global session handling is also possible:

        sub authenticate {
            my $r = shift;
            $r->public;
            if ( $r->table eq 'products' && $r->action eq 'search' ) {
                $r->private;
                $r->template('login') unless $r->user;
            }
            elsif ( $r->table eq 'products' && $r->action eq 'edit' ) {
                $r->restricted;
                $r->template('login') unless $r->user;
            }
            return OK;
        }

DESCRIPTION
    This module is based on Maypole::Authentication::UserSessionCookie but
    adds some more advanced features.

    Note that you need Maypole 2.0 or newer to use this module.

    For example we have three levels of security:

            Public: No authentication, only session management
           Private: Authenticate once, go everywhere
        Restricted: Authenticate and reauthorize with a ticket for every
                    request (best used in a post form as hidden input)

    The configuration works similar to
    Maypole::Authentication::UserSessionCookie but with some little
    additions.

        $r->{session_id} can be used from parse_path() for example,
        useful if the user has cookies disabled.

    We provide a number of methods to be inherited by a Maypole class. The
    three methods "public", "private" and "restricted" determine the
    security level.

  public
        $r->public;

    "public" checks for a session cookie and looks into the "session_id"
    slot of the Maypole request and then populates the resulting session
    hash to the "session" slot.

  private
        $r->private;

    "private" does the same as public but also calls "check_credentials" if
    you haven't authorized before. If the login was successful it populates
    a "User" object to the "user" slot of the Maypole object.

  restricted
        $r->restricted;

    "restricted" does the same as "private" but also calls "ticket".

  login
    This method creates the session hash. It also sets
    "$r-"{template_args}{session}> and "$r-"{template_args}{session_id}>.

  logout
    This method deletes the session hash.

  check_credentials
    This method checks for two form parameters (typically "user" and
    "password" but configurable) and does a "search" on the user class for
    those values. If the credentials are wrong, then
    "$r-"{template_args}{login_error}> is set to an error string.

  uid_to_user
    This method returns the result of a "retrieve" on the UID from the user
    class.

  ticket
    This method checks for a form parameter, "ticket" and reauthorizes the
    user whenever it is called. By default the ticket is just a serialized
    array represented as hex string containing the user and the password,
    but it is very simple to overload "ticket" with a better method. Use a
    Crypt:: module or even Kerberos! It also sets
    $r->{template_args}{ticket}.

TODO
    Better documentation.

AUTHOR
    Sebastian Riedel, "sri@cpan.org"

COPYRIGHT
    Copyright 2004 Sebastian Riedel. All rights reserved.

    This program is free software, you can redistribute it and/or modify it
    under the same terms as Perl itself.

