kivitendo/SL/Auth/HTTPHeaders.pm @ dd9732d8
f7417f07 | Moritz Bunkus | package SL::Auth::HTTPHeaders;
|
||
use List::MoreUtils qw(any);
|
||||
use SL::Auth::Constants qw(:all);
|
||||
use strict;
|
||||
my @required_config_options = qw(secret_header secret user_header client_id_header);
|
||||
sub new {
|
||||
my $type = shift;
|
||||
my $self = {};
|
||||
$self->{config} = shift;
|
||||
bless $self, $type;
|
||||
return $self;
|
||||
}
|
||||
sub reset {
|
||||
my ($self) = @_;
|
||||
}
|
||||
sub _env_var_for_header {
|
||||
my ($header) = @_;
|
||||
$header =~ s{-}{_}g;
|
||||
return $ENV{'HTTP_' . uc($header)};
|
||||
}
|
||||
sub _authenticate {
|
||||
my ($self, $type) = @_;
|
||||
my $secret = _env_var_for_header($self->{config}->{secret_header}) // '';
|
||||
if ($secret ne $self->{config}->{secret}) {
|
||||
$::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: bad secret sent by upstream server: $secret");
|
||||
return (ERR_BACKEND);
|
||||
}
|
||||
my $client_id = _env_var_for_header($self->{config}->{client_id_header});
|
||||
if (!$client_id) {
|
||||
$::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: no client ID header found");
|
||||
return (ERR_PASSWORD);
|
||||
}
|
||||
# $::auth->set_client();
|
||||
my $user = _env_var_for_header($self->{config}->{user_header});
|
||||
if (!$user) {
|
||||
$::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: no user name header found");
|
||||
return (ERR_PASSWORD);
|
||||
}
|
||||
$::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: OK client $client_id user $user");
|
||||
return (OK, $client_id, $user);
|
||||
}
|
||||
sub authenticate {
|
||||
my ($self) = @_;
|
||||
my ($status, $client, $login) = $self->_authenticate('authenticate');
|
||||
return $status;
|
||||
}
|
||||
sub can_change_password {
|
||||
return 0;
|
||||
}
|
||||
sub requires_cleartext_password {
|
||||
return 0;
|
||||
}
|
||||
sub change_password {
|
||||
return ERR_BACKEND;
|
||||
}
|
||||
sub verify_config {
|
||||
my $self = shift;
|
||||
my $cfg = $self->{config};
|
||||
if (!$cfg) {
|
||||
die 'config/kivitendo.conf: Key "authentication/http_headers" is missing.';
|
||||
}
|
||||
foreach (@required_config_options) {
|
||||
next if $cfg->{$_};
|
||||
die 'config/kivitendo.conf: Missing parameter in "authentication/http_headers": ' . $_;
|
||||
}
|
||||
}
|
||||
5a00c5be | Moritz Bunkus | =pod
|
||
=encoding utf8
|
||||
=head1 NAME
|
||||
SL::Auth::HTTPHeaders - Automatically log in users based on headers
|
||||
sent by upstream servers
|
||||
=head1 OVERVIEW
|
||||
This module implements two modes for automatic log in for users:
|
||||
=over 4
|
||||
=item HTTP Basic Authentication
|
||||
=item passing user name & client ID via arbitrary headers
|
||||
=back
|
||||
The module must be enabled in the configuration file by setting
|
||||
C<authentication.module=HTTPHeaders>. It is then configured by the
|
||||
sections C<authentication/http_basic> & C<authentication/http_headers>.
|
||||
=head1 SUPPORTED AUTHENTICATION METHODS
|
||||
=head2 User name & client ID in HTTP headers
|
||||
Must be enabled by setting
|
||||
C<authentication/http_headers.enabled=1>. If enabled, it relies on
|
||||
upstream servers (web server, proxy server) doing the authentication
|
||||
with SSO solutions like Authelia & Authentik. These solutions must
|
||||
then send the user name of the authenticated user in an HTTP header &
|
||||
the desired client ID in another header.
|
||||
In order to ensure no malicious third party can simply set these
|
||||
header values, a shared secret must be configured in the configuration
|
||||
file & sent along in a third header field.
|
||||
The names of all three headers as well as the shared secret must be
|
||||
set in the configuration file's C<authentication/http_headers>
|
||||
section.
|
||||
This mode is mutually exclusive with the HTTP Basic Authentication
|
||||
mentioned below.
|
||||
=head2 HTTP Basic Authentication (RFC 7617)
|
||||
Must be enabled by setting C<authentication/http_basic.enabled=1>. If
|
||||
enabled, it relies on the web server doing the authentication for it &
|
||||
passing the result in the C<Authorization> header, which turns into e
|
||||
environment variable C<HTTP_AUTHORIZATION> according to the CGI
|
||||
specifications.
|
||||
This mode only supports using the default client as no way to pass the
|
||||
desired client ID has been implemented yet.
|
||||
This mode is mutually exclusive with the "User name & client ID in
|
||||
HTTP headers" mode mentioned above.
|
||||
=head1 AUTHOR
|
||||
Moritz Bunkus E<lt>m.bunkus@linet.deE<gt>
|
||||
=cut
|
||||
f7417f07 | Moritz Bunkus | 1;
|