]> wagnertech.de Git - mfinanz.git/blob - SL/Auth/HTTPHeaders.pm
restart apache2 in postinst
[mfinanz.git] / SL / Auth / HTTPHeaders.pm
1 package SL::Auth::HTTPHeaders;
2
3 use List::MoreUtils qw(any);
4
5 use SL::Auth::Constants qw(:all);
6
7 use strict;
8
9 my @required_config_options = qw(secret_header secret user_header client_id_header);
10
11 sub new {
12   my $type        = shift;
13   my $self        = {};
14   $self->{config} = shift;
15
16   bless $self, $type;
17
18   return $self;
19 }
20
21 sub reset {
22   my ($self) = @_;
23 }
24
25 sub _env_var_for_header {
26   my ($header) = @_;
27
28   $header =~ s{-}{_}g;
29   return $ENV{'HTTP_' . uc($header)};
30 }
31
32 sub _authenticate {
33   my ($self, $type) = @_;
34
35   my $secret = _env_var_for_header($self->{config}->{secret_header}) // '';
36   if ($secret ne $self->{config}->{secret}) {
37     $::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: bad secret sent by upstream server: $secret");
38     return (ERR_BACKEND);
39   }
40
41   my $client_id = _env_var_for_header($self->{config}->{client_id_header});
42   if (!$client_id) {
43     $::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: no client ID header found");
44     return (ERR_PASSWORD);
45   }
46
47   # $::auth->set_client();
48
49   my $user = _env_var_for_header($self->{config}->{user_header});
50   if (!$user) {
51     $::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: no user name header found");
52     return (ERR_PASSWORD);
53   }
54
55   $::lxdebug->message(LXDebug->DEBUG2(), "HTTPHeaders ${type}: OK client $client_id user $user");
56
57   return (OK, $client_id, $user);
58 }
59
60 sub authenticate {
61   my ($self) = @_;
62
63   my ($status, $client, $login) = $self->_authenticate('authenticate');
64
65   return $status;
66 }
67
68 sub can_change_password {
69   return 0;
70 }
71
72 sub requires_cleartext_password {
73   return 0;
74 }
75
76 sub change_password {
77   return ERR_BACKEND;
78 }
79
80 sub verify_config {
81   my $self = shift;
82   my $cfg  = $self->{config};
83
84   if (!$cfg) {
85     die 'config/kivitendo.conf: Key "authentication/http_headers" is missing.';
86   }
87
88   foreach (@required_config_options) {
89     next if $cfg->{$_};
90     die 'config/kivitendo.conf: Missing parameter in "authentication/http_headers": ' . $_;
91   }
92 }
93
94 =pod
95
96 =encoding utf8
97
98 =head1 NAME
99
100 SL::Auth::HTTPHeaders - Automatically log in users based on headers
101 sent by upstream servers
102
103 =head1 OVERVIEW
104
105 This module implements two modes for automatic log in for users:
106
107 =over 4
108
109 =item HTTP Basic Authentication
110
111 =item passing user name & client ID via arbitrary headers
112
113 =back
114
115 The module must be enabled in the configuration file by setting
116 C<authentication.module=HTTPHeaders>. It is then configured by the
117 sections C<authentication/http_basic> & C<authentication/http_headers>.
118
119 =head1 SUPPORTED AUTHENTICATION METHODS
120
121 =head2 User name & client ID in HTTP headers
122
123 Must be enabled by setting
124 C<authentication/http_headers.enabled=1>. If enabled, it relies on
125 upstream servers (web server, proxy server) doing the authentication
126 with SSO solutions like Authelia & Authentik. These solutions must
127 then send the user name of the authenticated user in an HTTP header &
128 the desired client ID in another header.
129
130 In order to ensure no malicious third party can simply set these
131 header values, a shared secret must be configured in the configuration
132 file & sent along in a third header field.
133
134 The names of all three headers as well as the shared secret must be
135 set in the configuration file's C<authentication/http_headers>
136 section.
137
138 This mode is mutually exclusive with the HTTP Basic Authentication
139 mentioned below.
140
141 =head2 HTTP Basic Authentication (RFC 7617)
142
143 Must be enabled by setting C<authentication/http_basic.enabled=1>. If
144 enabled, it relies on the web server doing the authentication for it &
145 passing the result in the C<Authorization> header, which turns into e
146 environment variable C<HTTP_AUTHORIZATION> according to the CGI
147 specifications.
148
149 This mode only supports using the default client as no way to pass the
150 desired client ID has been implemented yet.
151
152 This mode is mutually exclusive with the "User name & client ID in
153 HTTP headers" mode mentioned above.
154
155 =head1 AUTHOR
156
157 Moritz Bunkus E<lt>m.bunkus@linet.deE<gt>
158
159 =cut
160
161 1;