Apache-AppSamurai
view release on metacpan or search on metacpan
lib/Apache/AppSamurai/AuthBasic.pm view on Meta::CPAN
# Apache::AppSamurai::AuthBasic - AppSamurai authentication against webserver
# using basic authentication.
# $Id: AuthBasic.pm,v 1.18 2008/04/30 21:40:05 pauldoom Exp $
##
# Copyright (c) 2008 Paul M. Hirsch (paul@voltagenoir.org).
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself.
##
package Apache::AppSamurai::AuthBasic;
use strict;
use warnings;
use vars qw($VERSION @ISA);
$VERSION = substr(q$Revision: 1.18 $, 10, -1);
use Carp;
use Apache::AppSamurai::AuthBase;
# Below is used to make client connection to backend server to test auth
# and collect any cookies we want to keep
use LWP::UserAgent;
use HTTP::Request;
use MIME::Base64;
@ISA = qw( Apache::AppSamurai::AuthBase );
sub Configure {
my $self = shift;
# Pull defaults from AuthBase and save.
$self->SUPER::Configure();
my $conft = $self->{conf};
# Initial configuration. Put defaults here before the @_ args are
# pulled in.
$self->{conf} = { %{$conft},
LoginUrl => 'https://127.0.0.1', # URL to authenticate
# aginst
KeepAuth => 0, # Keep Authorization: Basic XXX header
# and continue to send to the proxied
# servers. BE CAREFUL!
PassBackCookies => 0, # Pass all Set-Cookies back to
# client browser
AllowRedirect => 0, # Follow redirects (Keep off and get
# the URL right!)
UserAgent => '', # The User-Agent: header to report
RequireRealm => '', # If set, this realm must match that
# returned by the backend server
SuccessCode => 200, # Auth considered a failure unless
# this code is returned after login
Timeout => 10, # Timeout for connecting to auth server
PassMin => 3,
PassChars => '\w\d !\@\#\$\%\^\&\*,\.\?\-_=\+', # NOTE:
# No : since that perplexes Mr.
# Basic Auth
@_,
};
return 1;
}
sub Initialize {
my $self = shift;
# Holding space for alterlist items
$self->{alterlist} = {};
# Create LWP client and empty request
$self->{client} = new LWP::UserAgent(timeout => $self->{conf}{Timeout});
($self->{client}) || ($self->AddError("Initialization of LWP::UserAgent failed: $!") && return 0);
$self->{request} = new HTTP::Request("GET", $self->{conf}{LoginUrl});
($self->{request}) || ($self->AddError("Initialization of HTTP::Request failed: $!") && return 0);
# Turn off all redirects if configured
($self->{conf}{AllowRedirect} == 1) || ($self->{client}->requests_redirectable([]));
# Set the User-Agent for the request (You may want to use
# "HEADER:User-Agent" as the value in your Apache config. AppSamurai.pm
# will fill in the client's User-Agent: header value per-request, then.)
($self->{conf}{UserAgent} eq '') || ($self->{request}->header('User-Agent' => $self->{conf}{UserAgent}));
$self->{init} = 1;
return 1;
}
# Connect to the server to check that authentication is required,
# then send a second request with authentication and check for
# good return code
sub Authenticator {
my $self = shift;
my $user = shift;
my $pass = shift;
my ($response, $error, @tmp, $check, $realm);
# Initial connect and check return for 401
# Note - This pre-check is to make sure the target is actually listening
$response = $self->{client}->request($self->{request});
if ($response->code() != 401) {
# Well, that ain't right!
$self->AddError('error', "Failure or bad return code while connecting to \"" . $self->{conf}{LoginUrl} . "\": Code \"" . $response->code() . "\", $!");
return 0;
}
# Check for Basic in the list of WWW-Authorization values and
# optional realm
@tmp = $response->header("WWW-Authenticate");
$check = 0;
foreach (@tmp) {
if (/^basic( realm=\"([^\"]*?)\")?$/i) {
$realm = $2;
if ($self->{conf}{RequireRealm} ne '') {
# Note - Realm matched without case sensitivity.
unless ($realm =~ /^\Q$self->{conf}{RequireRealm}\E$/i) {
$self->AddError('error', "URL \"" . $self->{conf}{LoginUrl} . "\" returned the wrong realm: \"" . $realm . "\" (Check BasicAuthRequireRealm setting)");
return 0;
}
}
$check = 1;
last;
}
}
unless ($check) {
$self->AddError('error', "URL \"" . $self->{conf}{LoginUrl} . "\" did not list \"Basic\" as an allowed authentication method");
return 0;
}
# Set credentials in request
$self->{request}->authorization_basic($user, $pass);
lib/Apache/AppSamurai/AuthBasic.pm view on Meta::CPAN
a very quick look at how to do it. After that, check out
L<http://en.wikipedia.org/wiki/HTTP> or the HTTP RFCs for more info.)
=head2 I<SuccessCode> C<CODE>
(Default: 200)
This is the numerical HTTP response code the auth module should expect from
the auth server if the login was a success. 200 is usually correct.
B<Verifying this code is highly recommended!> Some servers and apps return
a 200 on various failures. (In part, thanks to Internet Explorer's "helpful"
error handling feature that displays its usual generic "Uh, something
happened!" error message on code 500 and other errors that return a page
under a certain length.)
=head2 I<Timeout> C<SECONDS>
(Default: 10)
The number of seconds to wait for the auth server to respond.
=head2 I<PassChars> C<REGEX-CHARS>
(Default: C<< \w\d !\@\#\$\%\^\&\*,\.\?\-_=\+ >>)
This is actually a configuration item included in Apache::AppSamurai::AuthBase.
It is mentioned here because the AuthBasic version overrides the usual
default by removing the C<:> character. (C<:> is used to split the username
and password inside the Base64 encoded authorization header.)
=head2 OTHERS
All other configuration items are inherited from
L<Apache::AppSamurai::AuthBase|Apache::AppSamurai::AuthBase>. Consult
its documentation for more information.
=head1 METHODS
=head2 Configure()
Other than the AuthBasic specific configuration options, (described in
L</USAGE>), this is just a wrapper for the AuthBase C<Configure()>.
=head2 Initialize()
Performs the following additional actions:
=over 4
=item *
Creates C<< %{$self->{alterlist}} >> to hold header and cookie alterlist
rules. (See L<Apache::AppSamurai|Apache::AppSamurai> for alterlist
information.)
=item *
Creates a L<LWP::UserAgent|LWP::UserAgent> instance and saves it in
C<< $self->{client} >>.
=item *
Creates a L<HTTP::Request|HTTP::Request> instance, containing the auth
server URL, and saves it in C<< $self->{request} >>.
=item *
If C<UserAgent> is set, collects (if C<header:> is used), then sets the
C<User-Agent> header in the request.
=back
=head2 Authenticator()
Performs the following actions, logging error(s) and returning 0 if any
actions fail:
=over 4
=item *
Makes an initial connection to the auth server URL and checks for a
C<401 Authorization Required> response code.
=item *
Checks that C<Basic> is listed as a supported type.
=item *
If C<RequireRealm> is configured, the realm returned by the auth server
is checked against the C<RequireRealm> value.
=item *
A second request is sent, this time with the username and password (credential)
included.
=item *
The return code is checked against C<SuccessCode>
=item *
If C<PassBackCookies> is 1, the cookies set by the auth server are saved
in the alterlist cookie hash with "passback" rules.
=item *
If C<KeepAuth> is 1, the authorization header (containing the username and
password) are saved in the alterlist header hash with an "add" rule.
=item *
If all checks have succeeded, 1 is returned.
=back
=head1 EXAMPLES
See L</SYNOPSIS> for a basic example, or configuration examples in
F<examples/conf/> inside the Apache::AppSamurai distribution.
=head1 SEE ALSO
L<Apache::AppSamurai>, L<Apache::AppSamurai::AuthBase>, L<LWP::UserAgent>,
L<HTTP::Request>
=head1 AUTHOR
Paul M. Hirsch, C<< <paul at voltagenoir.org> >>
=head1 BUGS
See L<Apache::AppSamurai> for information on bug submission and tracking.
=head1 SUPPORT
See L<Apache::AppSamurai> for support information.
=head1 COPYRIGHT & LICENSE
Copyright 2008 Paul M. Hirsch, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut
( run in 0.674 second using v1.01-cache-2.11-cpan-39bf76dae61 )