Apache-AppSamurai
view release on metacpan or search on metacpan
lib/Apache/AppSamurai/AuthBasic.pm view on Meta::CPAN
($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);
# Connect with beans and check return
$response = $self->{client}->request($self->{request});
if ($response->code() == $self->{conf}{SuccessCode}) {
# YAY! Now collect and store cookies and headers as directed
if (($self->{conf}{PassBackCookies}) && (@tmp = $response->header('set-cookie'))) {
foreach (@tmp) {
# Trim whitespace
s/^\s*(.*?)\s*$/$1/;
# Add to cookie alterlist for instance (will be sent back to web browser)
push(@{$self->{alterlist}->{cookie}}, "passback:$1");
}
}
if ($self->{conf}{KeepAuth}) {
push(@{$self->{alterlist}->{header}}, "add:Authorization:Basic " . encode_base64($user . ":" . $pass, ''));
}
return 1;
}
# Save errors
if ($error = $response->status_line) {
$self->AddError('warn', "URL \"" . $self->{conf}{LoginUrl} . "\", Authentication failure: \"$user\": $error");
} else {
$self->AddError('error', "URL \"" . $self->{conf}{LoginUrl} . "\", Fatal authentication failure: \"$user\": $!");
}
# DEFAULT DENY #
return 0;
}
1; # End of Apache::AppSamurai::AuthBasic
__END__
=head1 NAME
Apache::AppSamurai::AuthBasic - Check credentials against backend web server
using HTTP basic auth
=head1 SYNOPSIS
The module is selected and configured inside the Apache configuration.
# Example with an authname of "fred" for use as part of an Apache config.
# Configure as an authentication method
PerlSetVar fredAuthMethods "AuthBasic"
# The URL to send basic authentication checks to
PerlSetVar fredAuthBasicLoginUrl "https://someserver/somepath/"
# Use the special "HEADER:<field>" to pass the named header field from
# the client to the backend authenticator directly. (Optional)
PerlSetVar fredAuthBasicUserAgent "header:User-Agent"
# Abort the check unless the "realm" returned by the server matches
# this string. (Optional)
PerlSetVar fredAuthBasicRequireRealm "Fred World Login"
# Continue to send the same Authorization: header to the backend server
# after login. (Only use this when the AuthBasic check is run against
# the backend server you are protecting)
PerlSetVar fredAuthBasicKeepAuth 1
# Collect cookies from AuthBasic check and send back to the user's browser
# on login (This is the default behaviour)
PerlSetVar fredAuthBasicPassBackCookies 1
=head1 DESCRIPTION
This L<Apache::AppSamurai|Apache::AppSamurai> authentication module checks a
username and password against a backend webserver, (referred to as the "auth
server" below), using HTTP basic authentication (as defined in
L<RFC 2617|http://www.faqs.org/rfcs/rfc2617.html>). In general, the
auth server is the same as the server Apache::AppSamurai is protecting,
though it does not have to be.
B<It is not recommended that you use AuthBasic as the only authentication
method for an Apache::AppSamurai instance!> There are various types of
failures that could result in an erroneous login success. There are also
inherent weaknesses in the HTTP basic auth system.
=head1 USAGE
The basic L<Apache::AppSamurai::AuthBase|Apache::AppSamurai::AuthBase>
configuration options are supported. Additional options are described
below. The following must be preceeded by the auth name and the auth
module name, I<AuthBasic>. For example, if you wish to set the
C<LoginUrl> value for the auth name "Jerry", you would use:
PerlSetVar JerryAuthBasicLoginUrl "url"
The auth name and "AuthBasic" have been removed for clarity.
See L<Apache::AppSamurai|Apache::AppSamurai> for more general configuration
information, or the F<examples/conf/> directory in the Apache::AppSamurai
distribution for examples.
( run in 0.987 second using v1.01-cache-2.11-cpan-39bf76dae61 )