Apache-AuthCookie

 view release on metacpan or  search on metacpan

lib/Apache2/AuthCookie.pm  view on Meta::CPAN

package Apache2::AuthCookie;
$Apache2::AuthCookie::VERSION = '3.32';
# ABSTRACT: Perl Authentication and Authorization via cookies

use strict;

use Carp;
use base 'Apache2::AuthCookie::Base';
use Apache2::Const qw(OK DECLINED SERVER_ERROR HTTP_FORBIDDEN);
use Apache::AuthCookie::Util qw(is_blank);


sub authorize {
    my ($auth_type, $r) = @_;

    my $debug = $r->dir_config("AuthCookieDebug") || 0;

    $r->server->log_error('authorize() for '.$r->uri()) if $debug >= 3;

    return OK unless $r->is_initial_req; #only the first internal request

    if ($r->auth_type ne $auth_type) {
        $r->server->log_error("auth type mismatch $auth_type != ".$r->auth_type)
            if $debug >= 3;
        return DECLINED;
    }

    my $reqs_arr = $auth_type->decoded_requires($r) or return DECLINED;

    my $user = $auth_type->decoded_user($r);

    $r->server->log_error("authorize user=$user type=$auth_type") if $debug >=3;

    if (is_blank($user)) {
        # the authentication failed
        $r->server->log_error("No user authenticated", $r->uri);
        return HTTP_FORBIDDEN;
    }

    my $satisfy = $auth_type->get_satisfy($r);
    return SERVER_ERROR unless $auth_type->satisfy_is_valid($r,$satisfy);
    my $satisfy_all = $satisfy eq 'all';

    my ($forbidden);
    foreach my $req (@$reqs_arr) {
        my ($requirement, $args) = split /\s+/, $req->{requirement}, 2;
        $args = '' unless defined $args;
        $r->server->log_error("requirement := $requirement, $args") if $debug >= 2;

        if (lc($requirement) eq 'valid-user') {
            if ($satisfy_all) {
                next;
            }
            else {
                return OK;
            }
        }

        if ($requirement eq 'user') {
            if ($args =~ m/\b$user\b/) {
                next if $satisfy_all;
                return OK; # satisfy any
            }

            $forbidden = 1;
            next;
        }

        # Call a custom method
        my $ret_val = $auth_type->$requirement($r, $args);
        $r->server->log_error("$auth_type->$requirement returned $ret_val") if $debug >= 3;
        if ($ret_val == OK) {
            next if $satisfy_all;
            return OK; # satisfy any
        }

        # Nothing succeeded, deny access to this user.
        $forbidden = 1;
    }

    return $forbidden ? HTTP_FORBIDDEN : OK;
}


sub get_satisfy {
    my ($auth_type, $r) = @_;

    my $auth_name = $r->auth_name;

    return lc( $r->dir_config("${auth_name}Satisfy") || 'all' );

lib/Apache2/AuthCookie.pm  view on Meta::CPAN

=head2 custom_errors($r,@_): int

Note: this interface is experimental.

This method handles the server response when you wish to access the Apache
custom_response method. Any suitable response can be used. this is
particularly useful when implementing 'by directory' access control using
the user authentication information. i.e.

        /restricted
                /one            user is allowed access here
                /two            not here
                /three          AND here

The authen_ses_key method would return a normal response when the user attempts
to access 'one' or 'three' but return (NOT_FOUND, 'File not found') if an
attempt was made to access subdirectory 'two'. Or, in the case of expired
credentials, (AUTH_REQUIRED,'Your session has timed out, you must login
again').

  example 'custom_errors'

  sub custom_errors {
    my ($self,$r,$CODE,$msg) = @_;
    # return custom message else use the server's standard message
    $r->custom_response($CODE, $msg) if $msg;
    return($CODE);
  }

  where CODE is a valid code from Apache2::Const

=head1 ENCODING AND CHARACTER SETS

=head2 Encoding

AuthCookie provides support for decoding POST/GET data if you tell it what the
client encoding is.  You do this by setting the C<< ${auth_name}Encoding >>
setting in C<httpd.conf>.  E.g.:

 PerlSetVar WhateEverEncoding UTF-8
 # and you also need to arrange for charset=UTF-8 at the end of the
 # Content-Type header with something like:
 AddDefaultCharset UTF-8

Note that you B<can> use charsets other than C<UTF-8>, however, you need to
arrange for the browser to send the right encoding back to the server.

If you have turned on Encoding support by setting C<< ${auth_name}Encoding >>,
this has the following effects:

=over 4

=item *

The internal pure-perl params processing subclass will be used, even if
libapreq2 is installed.  libapreq2 does not have any support for encoding or
unicode.

=item *

POST/GET data intercepted by AuthCookie will be decoded to perl's internal
format using L<Encode/decode>.

=item *

The value stored in C<< $r-E<gt>user >> will be encoded as B<bytes>, not
characters using the configured encoding name.  This is because the value
stored by mod_perl is a C API string, and not a perl string.  You can use
L<decoded_user()> to get user string encoded using B<character> semantics.

=back

This does has some caveats:

=over 4

=item *

your L<authen_cred()> and L<authen_ses_key()> function is expected to return
a decoded username, either by passing it through L<Encode/decode()>, or, by
turning on the UTF8 flag if appropriate.

=item *

Due to the way HTTP works, cookies cannot contain non-ASCII characters.
Because of this, if you are including the username in your generated session
key, you will need to escape any non-ascii characters in the session key
returned by L<authen_cred()>.

=item *

Similarly, you must reverse this escaping process in L<authen_ses_key()> and
return a L<Encode/decode()> decoded username.  If your L<authen_cred()>
function already only generates ASCII-only session keys then you do not need to
worry about any of this.

=item *

The value stored in C<< $r-E<gt>user >> will be encoded using bytes semantics
using the configured B<Encoding>.  If you want the decoded user value, use
L<decoded_user()> instead.

=back

=head2 Requires

You can also specify what the charset is of the Apache C<< $r-E<gt>requires >>
data is by setting C<< ${auth_name}RequiresEncoding >> in httpd.conf.

E.g.:

 PerlSetVar WhatEverRequiresEncoding UTF-8

This will make it so that AuthCookie will decode your C<requires> directives
using the configured character set.  You really only need to do this if you
have used non-ascii characters in any of your C<requires> directives in
httpd.conf.  e.g.:

 requires user programmør

=head1 EXAMPLE

For an example of how to use Apache2::AuthCookie, you may want to check
out the test suite, which runs AuthCookie through a few of its paces.
The documents are located in t/eg/, and you may want to peruse
t/real.t to see the generated httpd.conf file (at the bottom of
real.t) and check out what requests it's making of the server (at the
top of real.t).

=head1 THE LOGIN SCRIPT

You will need to create a login script (called login.pl above) that
generates an HTML form for the user to fill out.  You might generate
the page using a ModPerl::Registry script, a HTML::Mason component, an Apache
handler, or perhaps even using a static HTML page.  It's usually useful to
generate it dynamically so that you can define the 'destination' field
correctly (see below).

The following fields must be present in the form:

=over 4

=item 1.

The ACTION of the form must be /LOGIN (or whatever you defined in your
server configuration as handled by the ->login() method - see example
in the SYNOPSIS section).

=item 2.

The various user input fields (username, passwords, etc.) must be
named 'credential_0', 'credential_1', etc. on the form.  These will
get passed to your authen_cred() method.

=item 3.

You must define a form field called 'destination' that tells
AuthCookie where to redirect the request after successfully logging
in.  Typically this value is obtained from C<$r-E<gt>prev-E<gt>uri>.
See the login.pl script in t/eg/.



( run in 1.940 second using v1.01-cache-2.11-cpan-39bf76dae61 )