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 )