View | Details | Raw Unified | Return to bug 7174
Collapse All | Expand All

(-)a/Koha/Auth.pm (+258 lines)
Line 0 Link Here
1
package Koha::Auth;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
#Define common packages
21
use Modern::Perl;
22
use Scalar::Util qw(blessed);
23
use Try::Tiny;
24
25
#Define Koha packages
26
use Koha::Auth::RequestNormalizer;
27
use Koha::Auth::Route::Password;
28
use Koha::Auth::Route::Cookie;
29
use Koha::Auth::Route::RESTV1;
30
31
#Define Exceptions
32
use Koha::Exception::BadParameter;
33
use Koha::Exception::Logout;
34
use Koha::Exception::UnknownProgramState;
35
36
use Koha::Libraries;
37
38
#Define the headers, POST-parameters and cookies extracted from the various web-frameworks'
39
# request-objects and passed to the authentication system as normalized values.
40
our @authenticationHeaders = ('X-Koha-Date', 'Authorization');
41
our @authenticationPOSTparams = ('password', 'userid', 'cardnumber', 'PT', 'branch', 'logout.x', 'koha_login_context');
42
our @authenticationCookies = ('CGISESSID'); #Really we should have only one of these.
43
44
=head authenticate
45
46
@PARAM3 HASHRef of authentication directives. Supported values:
47
            'inOPAC' => 1,    #Authentication context is in OPAC
48
            'inREST' => 'v1', #Authentication context is in REST API V1
49
            'inSC'   => 1,    #Authentication context is in the staff client
50
            'authnotrequired' => 1, #Disregard all Koha::Exception::LoginFailed||NoPermission-exceptions,
51
                                    #and authenticate as an anonymous user if normal authentication
52
                                    #fails.
53
@THROWS Koha::Exception::VersionMismatch
54
        Koha::Exception::BadSystemPreference
55
        Koha::Exception::BadParameter
56
        Koha::Exception::ServiceTemporarilyUnavailable
57
        Koha::Exception::LoginFailed
58
        Koha::Exception::NoPermission
59
        Koha::Exception::Logout, catch this and redirect the request to the logout page.
60
=cut
61
62
sub authenticate {
63
    my ($controller, $permissions, $authParams) = @_;
64
    my $rae = _authenticate_validateAndNormalizeParameters(@_); #Get the normalized request authentication elements
65
66
    my $borrower; #Each authentication route returns a Koha::Patron-object on success. We use this to generate the Context()
67
68
    ##Select the Authentication route.
69
    ##Routes are introduced in priority order, and if one matches, the other routes are ignored.
70
    try {
71
        #0. Logout
72
        if ($rae->{postParams}->{'logout.x'}) {
73
            clearUserEnvironment($rae->{cookies}->{CGISESSID}, $authParams);
74
            Koha::Exception::Logout->throw(error => "User logged out. Please redirect me!");
75
        }
76
        #1. Check for password authentication, including LDAP.
77
        if (not($borrower) && $rae->{postParams}->{koha_login_context} && ($rae->{postParams}->{userid} || $rae->{postParams}->{cardnumber}) && $rae->{postParams}->{password}) {
78
            $borrower = Koha::Auth::Route::Password::challenge($rae, $permissions, $authParams);
79
        }
80
        #2. Check for REST's signature-based authentication.
81
        #elsif ($rae->{headers}->{'Authorization'} && $rae->{headers}->{'Authorization'} =~ /Koha/) {
82
        if (not($borrower) && $rae->{headers}->{'Authorization'}) {
83
            $borrower = Koha::Auth::Route::RESTV1::challenge($rae, $permissions, $authParams);
84
        }
85
        #3. Check for the cookie. If cookies go stale, they block all subsequent authentication methods, so keep it down on this list.
86
        if (not($borrower) && $rae->{cookies}->{CGISESSID}) {
87
            $borrower = Koha::Auth::Route::Cookie::challenge($rae, $permissions, $authParams);
88
        }
89
        if (not($borrower)) { #HTTP CAS ticket or shibboleth or Persona not implemented
90
            #We don't know how to authenticate, or there is no authentication attempt.
91
            Koha::Exception::LoginFailed->throw(error => "Koha doesn't understand your authentication protocol.");
92
        }
93
    } catch {
94
        if (blessed($_)) {
95
            if ($_->isa('Koha::Exception::LoginFailed') || $_->isa('Koha::Exception::NoPermission')) {
96
                if ($authParams->{authnotrequired}) { #We failed to login, but we can continue anonymously.
97
                    $borrower = Koha::Patron->new();
98
                }
99
                else {
100
                    $_->rethrow(); #Anonymous login not allowed this time
101
                }
102
            }
103
            else {
104
                die $_; #Propagate other errors to the calling Controller to redirect as it wants.
105
            }
106
        }
107
        else {
108
            die $_; #Not a Koha::Exception-object
109
        }
110
    };
111
112
    my $session = setUserEnvironment($controller, $rae, $borrower, $authParams);
113
    my $cookie = Koha::Auth::RequestNormalizer::getSessionCookie($controller, $session);
114
115
    if ($ENV{KOHA_REST_API_DEBUG} > 2) {
116
        my @cc = caller(0);
117
        print "\n".$cc[3]."\nSESSIONID ".$session->id().", FIRSTNAME ".$session->param('firstname')."\n";
118
    }
119
120
    return ($borrower, $cookie);
121
}
122
123
=head _authenticate_validateAndNormalizeParameters
124
125
@PARAM1 CGI- or Mojolicious::Controller-object, this is used to identify which web framework to use.
126
@PARAM2 HASHRef or undef, Permissions HASH telling which Koha permissions the user must have, to access the resource.
127
@PARAM3 HASHRef or undef, Special authentication parameters, see authenticate()
128
@THROWS Koha::Exception::BadParameter, if validating parameters fails.
129
=cut
130
131
sub _authenticate_validateAndNormalizeParameters {
132
    my ($controller, $permissions, $authParams) = @_;
133
134
    #Validate $controller.
135
    my $requestAuthElements;
136
    if (blessed($controller) && $controller->isa('CGI')) {
137
        $requestAuthElements = Koha::Auth::RequestNormalizer::normalizeCGI($controller, \@authenticationHeaders, \@authenticationPOSTparams, \@authenticationCookies);
138
    }
139
    elsif (blessed($controller) && $controller->isa('Mojolicious::Controller')) {
140
        $requestAuthElements = Koha::Auth::RequestNormalizer::normalizeMojolicious($controller, \@authenticationHeaders, \@authenticationPOSTparams, \@authenticationCookies);
141
    }
142
    else {
143
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::authenticate():> The first parameter MUST be either a 'CGI'-object or a 'Mojolicious::Controller'-object");
144
    }
145
    #Validate $permissions
146
    unless (not($permissions) || (ref $permissions eq 'HASH')) {
147
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::authenticate():> The second parameter MUST be 'undef' or a HASHRef of Koha permissions. See C4::Auth::haspermission().");
148
    }
149
    #Validate $authParams
150
    unless (not($authParams) || (ref $authParams eq 'HASH')) {
151
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::authenticate():> The third parameter MUST be 'undef' or a HASHRef.");
152
    }
153
154
    return $requestAuthElements;
155
}
156
157
=head setUserEnvironment
158
Set the C4::Context::user_env() and CGI::Session.
159
160
Any idea why there is both the CGI::Session and C4::Context::usernenv??
161
=cut
162
163
sub setUserEnvironment {
164
    my ($controller, $rae, $borrower, $authParams) = @_;
165
166
    my $session = C4::Auth::get_session( $rae->{cookies}->{CGISESSID} || '' );
167
    if ($rae->{postParams} && $rae->{postParams}->{koha_login_context} && $rae->{postParams}->{koha_login_context} eq 'REST' &&
168
          (not($session->param('koha_login_context')) || $session->param('koha_login_context') ne 'REST') #Make sure we dont create new Sessions for users who want to login many times in a row.
169
       ) {
170
        #We are logging in a user using the REST API, so we need to create a new session context outside of the usual CGISESSID-cookie
171
        $session = C4::Auth::get_session();
172
        $session->param( 'koha_login_context', $rae->{postParams}->{koha_login_context} );
173
    }
174
175
    C4::Context->_new_userenv( $session->id );
176
177
    _determineUserBranch($rae, $borrower, $authParams, $session);
178
179
    #Then start setting remaining session parameters
180
    $session->param( 'number',       $borrower->borrowernumber );
181
    $session->param( 'id',           $borrower->userid );
182
    $session->param( 'cardnumber',   $borrower->cardnumber );
183
    $session->param( 'firstname',    $borrower->firstname );
184
    $session->param( 'surname',      $borrower->surname );
185
    $session->param( 'emailaddress', $borrower->email );
186
    #originIps contain all the IP's this request has been proxied through.
187
    #Get the last value. This is in line with how the CGI-layer deals with IP-based authentication.
188
    $session->param( 'ip',           $rae->{originIps}->[ -1 ] );
189
    $session->param( 'lasttime',     time() );
190
    $session->flush(); #CGI::Session recommends to flush since auto-flush is not guaranteed.
191
192
    #Finally configure the userenv.
193
    C4::Context->set_userenv(
194
        $session->param('number'),       $session->param('id'),
195
        $session->param('cardnumber'),   $session->param('firstname'),
196
        $session->param('surname'),      $session->param('branch'),
197
        $session->param('branchname'),   undef,
198
        $session->param('emailaddress'), $session->param('branchprinter'),
199
        $session->param('persona'),      $session->param('shibboleth')
200
    );
201
202
    return $session;
203
}
204
205
sub _determineUserBranch {
206
    my ($rae, $borrower, $authParams, $session) = @_;
207
208
    my ($branchcode, $branchname);
209
    if ($rae->{postParams}->{branch}) {
210
        #We are instructed to change the active branch
211
        $branchcode = $rae->{postParams}->{branch};
212
    }
213
    elsif ($session->param('branch') && $session->param('branch') ne 'NO_LIBRARY_SET') {
214
        ##Branch is already set
215
        $branchcode = $session->param('branch');
216
    }
217
    elsif ($borrower->branchcode) {
218
        #Default to the borrower's branch
219
        $branchcode = $borrower->branchcode;
220
    }
221
    else {
222
        #No borrower branch? This must be the superuser.
223
        $branchcode = 'NO_LIBRARY_SET';
224
        $branchname = 'NO_LIBRARY_SET';
225
    }
226
    unless ($branchname) {
227
        my $library = Koha::Libraries->find($branchcode);
228
        $branchname = $library->branchname if $library;
229
    }
230
    $session->param( 'branch',     $branchcode );
231
    $session->param( 'branchname', ($branchname || 'NO_LIBRARY_SET'));
232
}
233
234
=head clearUserEnvironment
235
236
Removes the active authentication
237
238
=cut
239
240
sub clearUserEnvironment {
241
    my ($sessionid, $authParams) = @_;
242
243
    my $session;
244
    unless (blessed($sessionid)) {
245
        $session = C4::Auth::get_session( $sessionid );
246
    }
247
    else {
248
        $session = $sessionid;
249
    }
250
251
    if (C4::Context->userenv()) {
252
        C4::Context::_unset_userenv( $session->id );
253
    }
254
    $session->delete();
255
    $session->flush();
256
}
257
258
1;
(-)a/Koha/Auth/Challenge.pm (+74 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
=head1 NAME Koha::Auth::Challenge
23
24
=head2 SYNOPSIS
25
26
This is a authentication challenge parent class.
27
All Challenge-objects must implement the challenge()-method.
28
29
=head SUBLASSING
30
31
package Koha::Auth::Challenge::YetAnotherChallenge;
32
33
use base qw('Koha::Auth::Challenge');
34
35
sub challenge {
36
    #Implement the parent method to make this subclass interoperable.
37
}
38
39
=head2 USAGE
40
41
    use Scalar::Util qw(blessed);
42
    try {
43
        ...
44
        Koha::Auth::Challenge::Version::challenge();
45
        Koha::Auth::Challenge::OPACMaintenance::challenge();
46
        Koha::Auth::Challenge::YetAnotherChallenge::challenge();
47
        ...
48
    } catch {
49
        if (blessed($_)) {
50
            if ($_->isa('Koha::Exception::VersionMismatch')) {
51
                ##handle exception
52
            }
53
            elsif ($_->isa('Koha::Exception::AnotherKindOfException')) {
54
                ...
55
            }
56
            ...
57
            else {
58
                warn "Unknown exception class ".ref($_)."\n";
59
                die $_; #Unhandled exception case
60
            }
61
        }
62
        else {
63
            die $_; #Not a Koha::Exception-object
64
        }
65
    };
66
67
=cut
68
69
sub challenge {
70
    #@OVERLOAD this "interface"
71
    warn caller()." doesn't implement challenge()\n";
72
}
73
74
1;
(-)a/Koha/Auth/Challenge/Cookie.pm (+88 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::Cookie;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
use C4::Auth;
24
use Koha::AuthUtils;
25
use Koha::Patrons;
26
27
use Koha::Exception::LoginFailed;
28
29
use base qw(Koha::Auth::Challenge);
30
31
=head challenge
32
STATIC
33
34
    Koha::Auth::Challenge::Cookie::challenge($cookieValue);
35
36
Checks if the given authentication cookie value matches a session, and checks if
37
the session is still active.
38
@PARAM1 String, hashed session key identifying a session in koha.sessions
39
@RETURNS Koha::Patron matching the verified and active session
40
@THROWS Koha::Exception::LoginFailed, if no session is found,
41
                                      if the session has expired,
42
                                      if the session IP address changes,
43
                                      if no borrower was found for the session
44
=cut
45
46
sub challenge {
47
    my ($cookie, $originIps) = @_;
48
49
    my $session = C4::Auth::get_session($cookie);
50
    Koha::Exception::LoginFailed->throw(error => "No session matching the given session identifier '$session'.") unless $session;
51
52
    # See if the given session is timed out
53
    if (isSessionExpired($session)) {
54
        Koha::Auth::clearUserEnvironment($session, {});
55
        Koha::Exception::LoginFailed->throw(error => "Session expired, please login again.");
56
    }
57
    # Check if we still access using the same IP than when the session was initialized.
58
    elsif ( C4::Context->preference('SessionRestrictionByIP')) {
59
60
        my $sameIpFound = grep {$session->param('ip') eq $_} @$originIps;
61
62
        unless ($sameIpFound) {
63
            Koha::Auth::clearUserEnvironment($session, {});
64
            Koha::Exception::LoginFailed->throw(error => "Session's client address changed, please login again.");
65
        }
66
    }
67
68
    #Get the Borrower-object
69
    my $userid   = $session->param('id');
70
    my $borrower = Koha::AuthUtils::checkKohaSuperuserFromUserid($userid);
71
    $borrower = Koha::Patrons->find({userid => $userid}) if not($borrower) && $userid;
72
    Koha::Exception::LoginFailed->throw(error => "Cookie authentication succeeded, but no borrower found with userid '".($userid || '')."'.")
73
            unless $borrower;
74
75
    $session->param( 'lasttime', time() );
76
    return $borrower;
77
}
78
79
sub isSessionExpired {
80
    my ($session) = @_;
81
82
    if ( ($session->param('lasttime') || 0) < (time()- C4::Auth::_timeout_syspref()) ) {
83
        return 1;
84
    }
85
    return 0;
86
}
87
88
1;
(-)a/Koha/Auth/Challenge/IndependentBranchesAutolocation.pm (+53 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::IndependentBranchesAutolocation;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
24
use Koha::Libraries;
25
26
use Koha::Exception::LoginFailed;
27
28
use base qw(Koha::Auth::Challenge);
29
30
=head challenge
31
32
If sysprefs 'IndependentBranches' and 'Autolocation' are active, checks if the user
33
is in the correct network region to login.
34
@PARAM1 String, branchcode of the branch the current user is authenticating in to.
35
@THROWS Koha::Exception::LoginFailed, if the user is in the wrong network segment.
36
=cut
37
38
sub challenge {
39
    my ($currentBranchcode) = @_;
40
41
    if ( $currentBranchcode && C4::Context->boolean_preference('IndependentBranches') && C4::Context->boolean_preference('Autolocation') ) {
42
        my $ip = $ENV{'REMOTE_ADDR'};
43
44
        my $branches = Koha::Libraries->search->unblessed;
45
        # we have to check they are coming from the right ip range
46
        my $domain = $branches->{$currentBranchcode}->{'branchip'};
47
        if ( $ip !~ /^$domain/ ) {
48
            Koha::Exception::LoginFailed->throw(error => "Branch '$currentBranchcode' is inaccessible from this network.");
49
        }
50
    }
51
}
52
53
1;
(-)a/Koha/Auth/Challenge/OPACMaintenance.pm (+44 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::OPACMaintenance;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
24
use base qw(Koha::Auth::Challenge);
25
26
use Koha::Exception::ServiceTemporarilyUnavailable;
27
28
=head challenge
29
STATIC
30
31
    Koha::Auth::Challenge::OPACMaintenance::challenge();
32
33
Checks if OPAC is under maintenance.
34
35
@THROWS Koha::Exception::ServiceTemporarilyUnavailable
36
=cut
37
38
sub challenge {
39
    if ( C4::Context->preference('OpacMaintenance') ) {
40
        Koha::Exception::ServiceTemporarilyUnavailable->throw(error => 'OPAC is under maintenance');
41
    }
42
}
43
44
1;
(-)a/Koha/Auth/Challenge/Password.pm (+127 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::Password;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Patrons;
23
use Koha::AuthUtils;
24
25
use base qw(Koha::Auth::Challenge);
26
27
use Koha::Exception::LoginFailed;
28
29
our @usernameAliasColumns = ('userid', 'cardnumber'); #Possible columns to treat as the username when authenticating. Must be UNIQUE in DB.
30
31
=head NAME Koha::Auth::Challenge::Password
32
33
=head SYNOPSIS
34
35
This module implements the more specific behaviour of the password authentication component.
36
37
=cut
38
39
=head challenge
40
STATIC
41
42
    Koha::Auth::Challenge::Password::challenge();
43
44
@RETURN Koha::Patron-object if check succeedes, otherwise throws exceptions.
45
@THROWS Koha::Exception::LoginFailed from Koha::AuthUtils password checks.
46
=cut
47
48
sub challenge {
49
    my ($userid, $password) = @_;
50
51
    my $borrower;
52
    if (C4::Context->config('useldapserver')) {
53
        $borrower = Koha::Auth::Challenge::Password::checkLDAPPassword($userid, $password);
54
        return $borrower if $borrower;
55
    }
56
    if (C4::Context->preference('casAuthentication')) {
57
        warn("Koha::Auth doesn't support CAS-authentication yet. Please refactor the CAS client implementation to work with Koha::Auth. It cant be too hard :)");
58
    }
59
    if (C4::Context->config('useshibboleth')) {
60
        warn("Koha::Auth doesn't support Shibboleth-authentication yet. Please refactor the Shibboleth client implementation to work with Koha::Auth. It cant be too hard :)");
61
    }
62
63
    return Koha::Auth::Challenge::Password::checkKohaPassword($userid, $password);
64
}
65
66
=head checkKohaPassword
67
68
    my $borrower = Koha::Auth::Challenge::Password::checkKohaPassword($userid, $password);
69
70
Checks if the given username and password match anybody in the Koha DB
71
@PARAM1 String, user identifier, either the koha.borrowers.userid, or koha.borrowers.cardnumber
72
@PARAM2 String, clear text password from the authenticating user
73
@RETURN Koha::Patron, if login succeeded.
74
                Sets Koha::Patron->isSuperuser() if the user is a superuser.
75
@THROWS Koha::Exception::LoginFailed, if no matching password was found for all username aliases in Koha.
76
=cut
77
78
sub checkKohaPassword {
79
    my ($userid, $password) = @_;
80
    my $borrower; #Find the borrower to return
81
82
    $borrower = Koha::AuthUtils::checkKohaSuperuser($userid, $password);
83
    return $borrower if $borrower;
84
85
    my $usernameFound = 0; #Report to the user if userid/barcode was found, even if the login failed.
86
    #Check for each username alias if we can confirm a login with that.
87
    for my $unameAlias (@usernameAliasColumns) {
88
        my $borrower = Koha::Patrons->find({$unameAlias => $userid});
89
        if ( $borrower ) {
90
            $usernameFound = 1;
91
            return $borrower if ( Koha::AuthUtils::checkHash( $password, $borrower->password ) );
92
        }
93
    }
94
95
    Koha::Exception::LoginFailed->throw(error => "Password authentication failed for the given ".( ($usernameFound) ? "password" : "username and password").".");
96
}
97
98
=head checkLDAPPassword
99
100
Checks if the given username and password match anybody in the LDAP service
101
@PARAM1 String, user identifier
102
@PARAM2 String, clear text password from the authenticating user
103
@RETURN Koha::Patron, or
104
            undef if we couldn't reliably contact the LDAP server so we should
105
            fallback to local Koha Password authentication.
106
@THROWS Koha::Exception::LoginFailed, if LDAP login failed
107
=cut
108
109
sub checkLDAPPassword {
110
    my ($userid, $password) = @_;
111
112
    #Lazy load dependencies because somebody might never need them.
113
    require C4::Auth_with_ldap;
114
115
    my ($retval, $cardnumber, $local_userid) = C4::Auth_with_ldap::checkpw_ldap($userid, $password);    # EXTERNAL AUTH
116
    if ($retval == -1) {
117
        Koha::Exception::LoginFailed->throw(error => "LDAP authentication failed for the given username and password");
118
    }
119
120
    if ($retval) {
121
        my $borrower = Koha::Patrons->find({userid => $local_userid});
122
        return $borrower;
123
    }
124
    return undef;
125
}
126
127
1;
(-)a/Koha/Auth/Challenge/Permission.pm (+42 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::Permission;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::PermissionManager;
23
24
use base qw(Koha::Auth::Challenge);
25
26
=head challenge
27
STATIC
28
29
    Koha::Auth::Challenge::Permission::challenge($borrower, $permissionsRequired);
30
31
@THROWS Koha::Exception::NoPermission with the missing permission if permissions
32
                are inadequate
33
=cut
34
35
sub challenge {
36
    my ($borrower, $permissionsRequired) = @_;
37
38
    my $permissionManager = Koha::Auth::PermissionManager->new();
39
    $permissionManager->hasPermissions($borrower, $permissionsRequired);
40
}
41
42
1;
(-)a/Koha/Auth/Challenge/RESTV1.pm (+179 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::RESTV1;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use DateTime::Format::HTTP;
22
use DateTime;
23
24
use Koha::Patrons;
25
26
use base qw(Koha::Auth::Challenge);
27
28
use Koha::Exception::LoginFailed;
29
use Koha::Exception::BadParameter;
30
use Koha::Exception::Parse;
31
32
=head challenge
33
34
    my $borrower = Koha::Auth::Challenge::RESTV1::challenge();
35
36
For authentication to succeed, the client have to send 2 HTTP
37
headers:
38
 - X-Koha-Date: the standard HTTP Date header complying to RFC 1123, simply wrapped to X-Koha-Date,
39
                since the w3-specification forbids setting the Date-header from javascript.
40
 - Authorization: the standard HTTP Authorization header, see below for how it is constructed.
41
42
=head2 HTTP Request example
43
44
GET /api/v1/borrowers/12 HTTP/1.1
45
Host: api.yourkohadomain.fi
46
X-Koha-Date: Mon, 26 Mar 2007 19:37:58 +0000
47
Authorization: Koha admin69:frJIUN8DYpKDtOLCwo//yllqDzg=
48
49
=head2 Constructing the Authorization header
50
51
-You brand the authorization header with "Koha"
52
-Then you give the userid/cardnumber of the user authenticating.
53
-Then the hashed signature.
54
55
The signature is a HMAC-SHA256-HEX hash of several elements of the request,
56
separated by spaces:
57
 - HTTP method (uppercase)
58
 - userid/cardnumber
59
 - X-Koha-Date-header
60
Signed with the Borrowers API key
61
62
The server then tries to rebuild the signature with each of the user's API keys.
63
If one matches the received signature, then authentication is almost OK.
64
65
To avoid requests to be replayed, the last request's X-Koha-Date-header is stored
66
in database and the authentication succeeds only if the stored Date
67
is lesser than the X-Koha-Date-header.
68
69
=head2 Constructing the signature example
70
71
Signature = HMAC-SHA256-HEX("HTTPS" + " " +
72
                            "/api/v1/borrowers/12?howdoyoudo=voodoo" + " " +
73
                            "admin69" + " " +
74
                            "760818212" + " " +
75
                            "frJIUN8DYpKDtOLCwo//yllqDzg="
76
                           );
77
78
=head
79
80
@PARAM1 HASHRef of Header name => values
81
@PARAM2 String, upper case request method name, eg. HTTP or HTTPS
82
@PARAM3 String the request uri
83
@RETURNS Koha::Patron if authentication succeeded.
84
@THROWS Koha::Exception::LoginFailed, if API key signature verification failed
85
@THROWS Koha::Exception::BadParameter
86
@THROWS Koha::Exception::UnknownObject, if we cannot find a Borrower with the given input.
87
=cut
88
89
sub challenge {
90
    my ($headers, $method, $uri) = @_;
91
92
    my $req_dt;
93
    eval {
94
        $req_dt = DateTime::Format::HTTP->parse_datetime( $headers->{'X-Koha-Date'} ); #Returns DateTime
95
    };
96
    if (not($req_dt) || $@) {
97
        Koha::Exception::BadParameter->throw(error => "X-Koha-Date HTTP-header [".$headers->{'X-Koha-Date'}."] is not well formed. It needs to be of RFC 1123 -date format, eg. 'X-Koha-Date: Wed, 09 Feb 1994 22:23:32 +0200'");
98
    }
99
100
    my $authorizationHeader = $headers->{'Authorization'};
101
    my ($req_username, $req_signature);
102
    if ($authorizationHeader =~ /^Koha (\S+?):(\w+)$/) {
103
        $req_username = $1;
104
        $req_signature = $2;
105
    }
106
    else {
107
        Koha::Exception::BadParameter->throw(error => "Authorization HTTP-header is not well formed. It needs to be of format 'Authorization: Koha userid:signature'");
108
    }
109
110
    my $borrower = Koha::Patrons->cast($req_username);
111
112
    my @apikeys = Koha::ApiKeys->search({
113
        borrowernumber => $borrower->borrowernumber,
114
        active => 1,
115
    });
116
    Koha::Exception::LoginFailed->throw(error => "User has no API keys. Please add one using the Staff interface or OPAC.") unless @apikeys;
117
118
    my $matchingApiKey;
119
    foreach my $apikey (@apikeys) {
120
        my $signature = makeSignature($method, $req_username, $headers->{'X-Koha-Date'}, $apikey);
121
122
        if ($signature eq $req_signature) {
123
            $matchingApiKey = $apikey;
124
            last();
125
        }
126
    }
127
128
    unless ($matchingApiKey) {
129
        Koha::Exception::LoginFailed->throw(error => "API key authentication failed.");
130
    }
131
132
    #Checking for message replay abuses or change control using ETAG shouldn't be done here, since we need to make valid request more often than every second.
133
    #unless ($matchingApiKey->last_request_time < $req_dt->epoch()) {
134
    #    Koha::Exception::BadParameter->throw(error => "X-Koha-Date HTTP-header is stale, expected later date than '".DateTime::Format::HTTP->format_datetime($req_dt)."'");
135
    #}
136
137
    $matchingApiKey->set({last_request_time => $req_dt->epoch()});
138
    $matchingApiKey->store();
139
140
    return $borrower;
141
}
142
143
sub makeSignature {
144
    my ($method, $userid, $headerXKohaDate, $apiKey) = @_;
145
146
    my $message = join(' ', uc($method), $userid, $headerXKohaDate);
147
    my $digest = Digest::SHA::hmac_sha256_hex($message, $apiKey->api_key);
148
149
    if ($ENV{KOHA_REST_API_DEBUG} > 2) {
150
        my @cc = caller(1);
151
        print "\n".$cc[3]."\nMAKESIGNATURE $method, $userid, $headerXKohaDate, ".$apiKey->api_key.", DIGEST $digest\n";
152
    }
153
154
    return $digest;
155
}
156
157
=head prepareAuthenticationHeaders
158
@PARAM1 Koha::Patron, to authenticate
159
@PARAM2 DateTime, OPTIONAL, the timestamp of the HTTP request
160
@PARAM3 HTTP verb, 'get', 'post', 'patch', 'put', ...
161
@RETURNS HASHRef of authentication HTTP header names and their values. {
162
            "X-Koha-Date" => "Mon, 26 Mar 2007 19:37:58 +0000",
163
            "Authorization" => "Koha admin69:frJIUN8DYpKDtOLCwo//yllqDzg=",
164
        }
165
=cut
166
167
sub prepareAuthenticationHeaders {
168
    my ($borrower, $dateTime, $method) = @_;
169
    $borrower = Koha::Patrons->cast($borrower);
170
171
    my $headerXKohaDate = DateTime::Format::HTTP->format_datetime(
172
                                                ($dateTime || DateTime->now( time_zone => C4::Context->tz() ))
173
                          );
174
    my $headerAuthorization = "Koha ".$borrower->userid.":".makeSignature($method, $borrower->userid, $headerXKohaDate, $borrower->getApiKey('active'));
175
    return {'X-Koha-Date' => $headerXKohaDate,
176
            'Authorization' => $headerAuthorization};
177
}
178
179
1;
(-)a/Koha/Auth/Challenge/Version.pm (+56 lines)
Line 0 Link Here
1
package Koha::Auth::Challenge::Version;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
use Koha;
24
25
use base qw(Koha::Auth::Challenge);
26
27
use Koha::Exception::VersionMismatch;
28
use Koha::Exception::BadSystemPreference;
29
30
=head challenge
31
STATIC
32
33
    Koha::Auth::Challenge::Version::challenge();
34
35
Checks if the DB version is valid.
36
37
@THROWS Koha::Exception::VersionMismatch, if versions do not match
38
@THROWS Koha::Exception::BadSystemPreference, if "Version"-syspref is not set.
39
                        This probably means that Koha has not been installed yet.
40
=cut
41
42
sub challenge {
43
    my $versionSyspref = C4::Context->preference('Version');
44
    unless ( $versionSyspref ) {
45
        Koha::Exception::BadSystemPreference->throw(error => "No Koha 'Version'-system preference defined. Koha needs to be installed.");
46
    }
47
48
    my $kohaversion = Koha::version();
49
    # remove the 3 last . to have a Perl number
50
    $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
51
    if ( $versionSyspref < $kohaversion ) {
52
        Koha::Exception::VersionMismatch->throw(error => "Database update needed. Database is 'v$versionSyspref' and Koha is 'v$kohaversion'");
53
    }
54
}
55
56
1;
(-)a/Koha/Auth/RequestNormalizer.pm (+178 lines)
Line 0 Link Here
1
package Koha::Auth::RequestNormalizer;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Scalar::Util qw(blessed);
23
24
25
=head normalizeCGI
26
27
Takes a CGI-object and finds the authentication markers from it.
28
@PARAM1 CGI-object.
29
@PARAM2 ARRAYRef, authentication headers that should be extracted for authentication
30
@PARAM3 ARRAYRef, authentication POST parameters that should be extracted for authentication
31
@PARAM4 ARRAYRef, authentication cookies that should be extracted for authentication
32
@RETURNS List of : HASHRef of headers required for authentication, or undef
33
                   HASHRef of POST parameters required for authentication, or undef
34
                   HASHRef of the authenticaton cookie name => value, or undef
35
=cut
36
37
sub normalizeCGI {
38
    my ($controller, $authenticationHeaders, $authenticationPOSTparams, $authenticationCookies) = @_;
39
40
    my ($headers, $postParams, $cookies) = ({}, {}, {});
41
    foreach my $authHeader (@$authenticationHeaders) {
42
        if (my $val = $controller->http($authHeader)) {
43
            $headers->{$authHeader} = $val;
44
        }
45
    }
46
    foreach my $authParam (@$authenticationPOSTparams) {
47
        if (my $val = $controller->param($authParam)) {
48
            $postParams->{$authParam} = $val;
49
        }
50
    }
51
    foreach my $authCookie (@$authenticationCookies) {
52
        if (my $val = $controller->cookie($authCookie)) {
53
            $cookies->{$authCookie} = $val;
54
        }
55
    }
56
57
    my $method = $1 if ($ENV{SERVER_PROTOCOL} =~ /^(.+?)\//);
58
59
    my @originIps = ($ENV{'REMOTE_ADDR'});
60
61
    my $requestAuthElements = { #Collect the authentication elements here.
62
        headers => $headers,
63
        postParams => $postParams,
64
        cookies => $cookies,
65
        originIps => \@originIps,
66
        method => $method,
67
        url => $ENV{REQUEST_URI},
68
    };
69
    return $requestAuthElements;
70
}
71
72
=head normalizeMojolicious
73
74
Takes a Mojolicious::Controller-object and finds the authentication markers from it.
75
@PARAM1 Mojolicious::Controller-object.
76
@PARAM2-4 See normalizeCGI()
77
@RETURNS HASHRef of the request's authentication elements marked for extraction, eg:
78
        {
79
            headers => { X-Koha-Signature => '32rFrFw3iojsev34AS',
80
                         X-Koha-Username => 'pavlov'},
81
            POSTparams => { password => '1234',
82
                            userid => 'pavlov'},
83
            cookies => { CGISESSID => '233FADFEV3as1asS' },
84
            method => 'https',
85
            url => '/borrower/12/holds'
86
        }
87
=cut
88
89
sub normalizeMojolicious {
90
    my ($controller, $authenticationHeaders, $authenticationPOSTparams, $authenticationCookies) = @_;
91
92
    my $request = $controller->req();
93
    my ($headers, $postParams, $cookies) = ({}, {}, {});
94
    my $headersHash = $request->headers()->to_hash();
95
    foreach my $authHeader (@$authenticationHeaders) {
96
        if (my $val = $headersHash->{$authHeader}) {
97
            $headers->{$authHeader} = $val;
98
        }
99
    }
100
    foreach my $authParam (@$authenticationPOSTparams) {
101
        if (my $val = $request->param($authParam)) {
102
            $postParams->{$authParam} = $val;
103
        }
104
    }
105
106
    my $requestCookies = $request->cookies;
107
    if (scalar(@$requestCookies)) {
108
        foreach my $authCookieName (@$authenticationCookies) {
109
            foreach my $requestCookie (@$requestCookies) {
110
                if ($authCookieName eq $requestCookie->name) {
111
                    $cookies->{$authCookieName} = $requestCookie->value;
112
                }
113
            }
114
        }
115
    }
116
117
    my @originIps = ($controller->tx->original_remote_address());
118
    push @originIps, $request->headers()->header('X-Forwarded-For') if $request->headers()->header('X-Forwarded-For');
119
120
    my $requestAuthElements = { #Collect the authentication elements here.
121
        headers => $headers,
122
        postParams => $postParams,
123
        cookies => $cookies,
124
        originIps => \@originIps,
125
        method => $controller->req->method,
126
        url => '/' . $controller->req->url->path_query,
127
    };
128
    return $requestAuthElements;
129
}
130
131
=head getSessionCookie
132
133
@PARAM1 CGI- or Mojolicious::Controller-object, this is used to identify which web framework to use.
134
@PARAM2 CGI::Session.
135
@RETURNS a Mojolicious cookie or a CGI::Cookie.
136
=cut
137
138
sub getSessionCookie {
139
    my ($controller, $session) = @_;
140
141
    my $cookie = {
142
            name     => 'CGISESSID',
143
            value    => $session->id,
144
    };
145
    my $cookieOk;
146
147
    if (blessed($controller)) {
148
        if ($controller->isa('CGI')) {
149
            $cookie->{HttpOnly} = 1;
150
            $cookieOk = $controller->cookie( $cookie );
151
        }
152
        elsif ($controller->isa('Mojolicious::Controller')) {
153
            my $cooksreq = $controller->req->cookies;
154
            my $cooksres = $controller->res->cookies;
155
            foreach my $c (@{$controller->res->cookies}) {
156
157
                if ($c->name eq 'CGISESSID') {
158
                    $c->value($cookie->{value});
159
                    $cookieOk = $c;
160
                }
161
            }
162
        }
163
    }
164
    #No auth cookie, so we must make one :)
165
    unless ($cookieOk) {
166
        $controller->res->cookies($cookie);
167
        my $cooks = $controller->res->cookies();
168
        foreach my $c (@$cooks) {
169
            if ($c->name eq 'CGISESSID') {
170
                $cookieOk = $c;
171
                last;
172
            }
173
        }
174
    }
175
    return $cookieOk;
176
}
177
178
1;
(-)a/Koha/Auth/Route.pm (+75 lines)
Line 0 Link Here
1
package Koha::Auth::Route;
2
3
use Modern::Perl;
4
5
# Copyright 2015 Vaara-kirjastot
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it
10
# under the terms of the GNU General Public License as published by
11
# the Free Software Foundation; either version 3 of the License, or
12
# (at your option) any later version.
13
#
14
# Koha is distributed in the hope that it will be useful, but
15
# WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License
20
# along with Koha; if not, see <http://www.gnu.org/licenses>.
21
22
=head
23
24
=NAME Koha::Auth::Route
25
26
=SYNOPSIS
27
28
This is an interface definition for Koha::Auth::Route::* -subclasses.
29
This documentation explains how to subclass different routes.
30
31
=USAGE
32
33
    if ($userid && $password) {
34
        $borrower = Koha::Auth::Route::<RouteName>::challenge($requestAuthElements, $permissionsRequired, $routeParams);
35
    }
36
37
=head INPUT
38
39
Each Route gets three parameters:
40
    $requestAuthElements, HASHRef of HASHRefs:
41
        headers =>      HASHRef of HTTP Headers matching the @authenticationHeaders-package
42
                        variable in Koha::Auth,
43
                        Eg. { 'X-Koha-Signature' => "23in4ow2gas2opcnpa", ... }
44
        postParams =>   HASHRef of HTTP POST parameters matching the
45
                        @authenticationPOSTparams-package variable in Koha::Auth,
46
                        Eg. { password => '1234', 'userid' => 'admin'}
47
        cookies =>      HASHRef of HTTP Cookies matching the
48
                        @authenticationPOSTparams-package variable in Koha::Auth,
49
                        EG. { CGISESSID => '9821rj1kn3tr9ff2of2ln1' }
50
    $permissionsRequired:
51
                        HASHRef of Koha permissions.
52
                        See Koha::Auth::PermissionManager for example.
53
    $routeParams:       HASHRef of special Route-related data
54
                        {inOPAC => 1, authnotrequired => 0, ...}
55
56
=head OUTPUT
57
58
Each route must return a Koha::Patron-object representing the authenticated user.
59
Even if the login succeeds with a superuser or similar virtual user, like
60
anonymous login, a mock Borrower-object must be returned.
61
If the login fails, each route must throw Koha::Exceptions to notify the cause
62
of the failure.
63
64
=head ROUTE STRUCTURE
65
66
Each route consists of Koha::Auth::Challenge::*-objects to test for various
67
authentication challenges.
68
69
See. Koha::Auth::Challenge for more information.
70
71
=cut
72
73
sub challenge {}; #@OVERLOAD this "interface"
74
75
1;
(-)a/Koha/Auth/Route/Cookie.pm (+44 lines)
Line 0 Link Here
1
package Koha::Auth::Route::Cookie;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::Challenge::OPACMaintenance;
23
use Koha::Auth::Challenge::Version;
24
use Koha::Auth::Challenge::Cookie;
25
use Koha::Auth::Challenge::Permission;
26
27
use base qw(Koha::Auth::Route);
28
29
=head challenge
30
See Koha::Auth::Route, for usage documentation.
31
@THROWS Koha::Exceptions from authentication components.
32
=cut
33
34
sub challenge {
35
    my ($rae, $permissionsRequired, $routeParams) = @_;
36
37
    Koha::Auth::Challenge::OPACMaintenance::challenge() if $routeParams->{inOPAC};
38
    Koha::Auth::Challenge::Version::challenge();
39
    my $borrower = Koha::Auth::Challenge::Cookie::challenge($rae->{cookies}->{CGISESSID}, $rae->{originIps});
40
    Koha::Auth::Challenge::Permission::challenge($borrower, $permissionsRequired) if $permissionsRequired;
41
    return $borrower;
42
}
43
44
1;
(-)a/Koha/Auth/Route/Password.pm (+46 lines)
Line 0 Link Here
1
package Koha::Auth::Route::Password;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::Challenge::OPACMaintenance;
23
use Koha::Auth::Challenge::Version;
24
use Koha::Auth::Challenge::IndependentBranchesAutolocation;
25
use Koha::Auth::Challenge::Password;
26
use Koha::Auth::Challenge::Permission;
27
28
use base qw(Koha::Auth::Route);
29
30
=head challenge
31
See Koha::Auth::Route, for usage documentation.
32
@THROWS Koha::Exceptions from authentication components.
33
=cut
34
35
sub challenge {
36
    my ($rae, $permissionsRequired, $routeParams) = @_;
37
38
    Koha::Auth::Challenge::OPACMaintenance::challenge() if $routeParams->{inOPAC};
39
    Koha::Auth::Challenge::Version::challenge();
40
    Koha::Auth::Challenge::IndependentBranchesAutolocation::challenge($routeParams->{branch});
41
    my $borrower = Koha::Auth::Challenge::Password::challenge($rae->{postParams}->{userid} || $rae->{postParams}->{cardnumber}, $rae->{postParams}->{password});
42
    Koha::Auth::Challenge::Permission::challenge($borrower, $permissionsRequired) if $permissionsRequired;
43
    return $borrower;
44
}
45
46
1;
(-)a/Koha/Auth/Route/RESTV1.pm (+43 lines)
Line 0 Link Here
1
package Koha::Auth::Route::RESTV1;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::Challenge::Version;
23
use Koha::Auth::Challenge::RESTV1;
24
use Koha::Auth::Challenge::Permission;
25
26
use base qw(Koha::Auth::Route);
27
28
=head challenge
29
See Koha::Auth::Route, for usage documentation.
30
@THROWS Koha::Exceptions from authentication components.
31
=cut
32
33
sub challenge {
34
    my ($rae, $permissionsRequired, $routeParams) = @_;
35
36
    #Koha::Auth::Challenge::RESTMaintenance::challenge() if $routeParams->{inREST}; #NOT IMPLEMENTED YET
37
    Koha::Auth::Challenge::Version::challenge();
38
    my $borrower = Koha::Auth::Challenge::RESTV1::challenge($rae->{headers}, $rae->{method}, $rae->{url});
39
    Koha::Auth::Challenge::Permission::challenge($borrower, $permissionsRequired) if $permissionsRequired;
40
    return $borrower;
41
}
42
43
1;
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt (-1 / +3 lines)
Lines 45-51 Link Here
45
<form action="[% script_name %]" method="post" name="loginform" id="loginform">
45
<form action="[% script_name %]" method="post" name="loginform" id="loginform">
46
    <input type="hidden" name="koha_login_context" value="intranet" />
46
    <input type="hidden" name="koha_login_context" value="intranet" />
47
[% FOREACH INPUT IN INPUTS %]
47
[% FOREACH INPUT IN INPUTS %]
48
    <input type="hidden" name="[% INPUT.name |html %]" value="[% INPUT.value |html %]" />
48
    [% UNLESS INPUT.name == 'logout.x' #No reason to send the logout-signal again %]
49
        <input type="hidden" name="[% INPUT.name |html %]" value="[% INPUT.value |html %]" />
50
    [% END %]
49
[% END %]
51
[% END %]
50
<p><label for="userid">Username:</label>
52
<p><label for="userid">Username:</label>
51
<input type="text" name="userid" id="userid" class="input focus" value="[% userid %]" size="20" tabindex="1" />
53
<input type="text" name="userid" id="userid" class="input focus" value="[% userid %]" size="20" tabindex="1" />
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (-1 / +3 lines)
Lines 154-160 Link Here
154
                            <input type="hidden" name="koha_login_context" value="opac" />
154
                            <input type="hidden" name="koha_login_context" value="opac" />
155
                            <fieldset class="brief">
155
                            <fieldset class="brief">
156
                            [% FOREACH INPUT IN INPUTS %]
156
                            [% FOREACH INPUT IN INPUTS %]
157
                                <input type="hidden" name="[% INPUT.name |html %]" value="[% INPUT.value |html %]" />
157
                                [% UNLESS INPUT.name == 'logout.x' #No reason to send the logout-signal again %]
158
                                    <input type="hidden" name="[% INPUT.name |html %]" value="[% INPUT.value |html %]" />
159
                                [% END %]
158
                            [% END %]
160
                            [% END %]
159
                            <label for="userid">Login</label>
161
                            <label for="userid">Login</label>
160
                            <input type="text"  size="25" id="userid"  name="userid" />
162
                            <input type="text"  size="25" id="userid"  name="userid" />
(-)a/opac/opac-search-history.pl (-1 lines)
Lines 41-47 my ($template, $loggedinuser, $cookie) = get_template_and_user( Link Here
41
        query => $cgi,
41
        query => $cgi,
42
        type => "opac",
42
        type => "opac",
43
        authnotrequired => 1,
43
        authnotrequired => 1,
44
        flagsrequired => {borrowers => 1},
45
        debug => 1,
44
        debug => 1,
46
    }
45
    }
47
);
46
);
(-)a/opac/opac-user.pl (-1 / +1 lines)
Lines 293-299 $template->param( Link Here
293
);
293
);
294
294
295
# current alert subscriptions
295
# current alert subscriptions
296
my $alerts = getalert($borrowernumber) if $borrowernumber;
296
my $alerts = getalert($borrowernumber) if $borrowernumber; #Superuser has no borrowernumber
297
foreach ( @$alerts ) {
297
foreach ( @$alerts ) {
298
    $_->{ $_->{type} } = 1;
298
    $_->{ $_->{type} } = 1;
299
    $_->{relatedto} = findrelatedto( $_->{type}, $_->{externalid} );
299
    $_->{relatedto} = findrelatedto( $_->{type}, $_->{externalid} );
(-)a/t/db_dependent/Koha/Borrower.t (-1 / +55 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Test::More; #Please don't set the test count here. It is nothing but trouble when rebasing against master and is of dubious help.
21
22
use Koha::Patron;
23
24
25
26
testIsSuperuser();
27
28
29
30
31
32
################################################################################
33
#### Define test subroutines here ##############################################
34
################################################################################
35
36
=head testIsSuperuser
37
@UNIT_TEST
38
Tests Koha::Borrower->isSuperuser()
39
=cut
40
41
sub testIsSuperuser {
42
    my $borrower = Koha::Patron->new();
43
    ok((not(defined($borrower->isSuperuser()))), "isSuperuser(): By default user is not defined as superuser.");
44
    ok(($borrower->isSuperuser(1) == 1), "isSuperuser(): Setting user as superuser returns 1.");
45
    ok(($borrower->isSuperuser() == 1), "isSuperuser(): Getting superuser status from a superuser returns 1.");
46
    ok((not(defined($borrower->isSuperuser(0)))), "isSuperuser(): Removing superuser status from a superuser OK and returns undef");
47
    ok((not(defined($borrower->isSuperuser()))), "isSuperuser(): Ex-superuser superuser status is undef");
48
}
49
50
51
52
53
#######################
54
done_testing(); #YAY!!
55
#######################

Return to bug 7174