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

(-)a/C4/Auth.pm (-8 / +67 lines)
Lines 36-42 use POSIX qw/strftime/; Link Here
36
use List::MoreUtils qw/ any /;
36
use List::MoreUtils qw/ any /;
37
37
38
# use utf8;
38
# use utf8;
39
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout);
39
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout $shib $shib_login);
40
40
41
BEGIN {
41
BEGIN {
42
    sub psgi_env { any { /^psgi\./ } keys %ENV }
42
    sub psgi_env { any { /^psgi\./ } keys %ENV }
Lines 55-66 BEGIN { Link Here
55
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
55
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
56
    $ldap        = C4::Context->config('useldapserver') || 0;
56
    $ldap        = C4::Context->config('useldapserver') || 0;
57
    $cas         = C4::Context->preference('casAuthentication');
57
    $cas         = C4::Context->preference('casAuthentication');
58
    $shib        = C4::Context->preference('shibbolethAuthentication');
58
    $caslogout   = C4::Context->preference('casLogout');
59
    $caslogout   = C4::Context->preference('casLogout');
59
    require C4::Auth_with_cas;             # no import
60
    require C4::Auth_with_cas;             # no import
61
    require C4::Auth_with_Shibboleth;
60
    if ($ldap) {
62
    if ($ldap) {
61
    require C4::Auth_with_ldap;
63
    require C4::Auth_with_ldap;
62
    import C4::Auth_with_ldap qw(checkpw_ldap);
64
    import C4::Auth_with_ldap qw(checkpw_ldap);
63
    }
65
    }
66
    if ($shib) {
67
        import C4::Auth_with_Shibboleth qw(checkpw_shib logout_shib login_shib_url get_login_shib);
68
        # Getting user login
69
        $shib_login = get_login_shib();
70
    }
64
    if ($cas) {
71
    if ($cas) {
65
        import  C4::Auth_with_cas qw(check_api_auth_cas checkpw_cas login_cas logout_cas login_cas_url);
72
        import  C4::Auth_with_cas qw(check_api_auth_cas checkpw_cas login_cas logout_cas login_cas_url);
66
    }
73
    }
Lines 670-677 sub checkauth { Link Here
670
    my $casparam = $query->param('cas');
677
    my $casparam = $query->param('cas');
671
    my $q_userid = $query->param('userid') // '';
678
    my $q_userid = $query->param('userid') // '';
672
679
673
    if ( $userid = $ENV{'REMOTE_USER'} ) {
680
    # Basic authentication is incompatible with the use of Shibboleth,
674
            # Using Basic Authentication, no cookies required
681
    # as Shibboleth may return REMOTE_USER as a Shibboleth attribute,
682
    # and it may not be the attribute we want to use to match the koha login.
683
    #
684
    # Also, do not consider an empty REMOTE_USER.
685
    #
686
    # Finally, after those tests, we can assume (although if it would be better with
687
    # a syspref) that if we get a REMOTE_USER, that's from basic authentication,
688
    # and we can affect it to $userid.
689
    if ( !$shib and $ENV{'REMOTE_USER'} ne '' and $userid = $ENV{'REMOTE_USER'} ) {
690
691
        # Using Basic Authentication, no cookies required
675
        $cookie = $query->cookie(
692
        $cookie = $query->cookie(
676
            -name     => 'CGISESSID',
693
            -name     => 'CGISESSID',
677
            -value    => '',
694
            -value    => '',
Lines 729-737 sub checkauth { Link Here
729
            $sessionID = undef;
746
            $sessionID = undef;
730
            $userid    = undef;
747
            $userid    = undef;
731
748
732
        if ($cas and $caslogout) {
749
            if ($cas and $caslogout) {
733
        logout_cas($query);
750
                logout_cas($query);
734
        }
751
            }
752
753
            # If we are in a shibboleth session (shibboleth is enabled, and a shibboleth username is set)
754
            if ( $shib and $shib_login and $type eq 'opac') {
755
            # (Note: $type eq 'opac' condition should be removed when shibboleth authentication for intranet will be implemented)
756
                logout_shib($query);
757
            }
735
        }
758
        }
736
        elsif ( !$lasttime || ($lasttime < time() - $timeout) ) {
759
        elsif ( !$lasttime || ($lasttime < time() - $timeout) ) {
737
            # timed logout
760
            # timed logout
Lines 801-813 sub checkauth { Link Here
801
        }
824
        }
802
        if (   ( $cas && $query->param('ticket') )
825
        if (   ( $cas && $query->param('ticket') )
803
            || $userid
826
            || $userid
827
            || $shib
804
            || $pki_field ne 'None'
828
            || $pki_field ne 'None'
805
            || $persona )
829
	    || $persona )
806
        {
830
        {
807
            my $password = $query->param('password');
831
            my $password = $query->param('password');
808
832
809
            my ( $return, $cardnumber );
833
            my ( $return, $cardnumber );
810
            if ( $cas && $query->param('ticket') ) {
834
            if ($shib && $shib_login && $type eq 'opac' && !$password) {
835
                my $retuserid;
836
                ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
837
                $userid = $retuserid;
838
                $info{'invalidShibLogin'} = 1 unless ($return);
839
840
            } elsif ( $cas && $query->param('ticket') ) {
811
                my $retuserid;
841
                my $retuserid;
812
                ( $return, $cardnumber, $retuserid ) =
842
                ( $return, $cardnumber, $retuserid ) =
813
                  checkpw( $dbh, $userid, $password, $query );
843
                  checkpw( $dbh, $userid, $password, $query );
Lines 1054-1059 sub checkauth { Link Here
1054
        login                => 1,
1084
        login                => 1,
1055
        INPUTS               => \@inputs,
1085
        INPUTS               => \@inputs,
1056
        casAuthentication    => C4::Context->preference("casAuthentication"),
1086
        casAuthentication    => C4::Context->preference("casAuthentication"),
1087
        shibbolethAuthentication => C4::Context->preference("shibbolethAuthentication"),
1057
        suggestion           => C4::Context->preference("suggestion"),
1088
        suggestion           => C4::Context->preference("suggestion"),
1058
        virtualshelves       => C4::Context->preference("virtualshelves"),
1089
        virtualshelves       => C4::Context->preference("virtualshelves"),
1059
        LibraryName          => "" . C4::Context->preference("LibraryName"),
1090
        LibraryName          => "" . C4::Context->preference("LibraryName"),
Lines 1124-1129 sub checkauth { Link Here
1124
        );
1155
        );
1125
    }
1156
    }
1126
1157
1158
    if ($shib) {
1159
            $template->param(
1160
                shibbolethLoginUrl    => login_shib_url($query),
1161
            );
1162
    }
1163
1127
    my $self_url = $query->url( -absolute => 1 );
1164
    my $self_url = $query->url( -absolute => 1 );
1128
    $template->param(
1165
    $template->param(
1129
        url         => $self_url,
1166
        url         => $self_url,
Lines 1557-1562 sub checkpw { Link Here
1557
        return 0;
1594
        return 0;
1558
    }
1595
    }
1559
1596
1597
    # If we are in a shibboleth session (shibboleth is enabled and no password has been provided)
1598
    if ($shib && !$password) {
1599
1600
        $debug and print STDERR "## checkpw - checking Shibboleth\n";
1601
        # In case of a Shibboleth authentication, we expect a shibboleth user attribute
1602
        # (defined in the shibbolethLoginAttribute) tto contain the login of the
1603
        # shibboleth-authenticated user
1604
1605
        # Shibboleth attributes are mapped into http environmement variables,
1606
        # so we're getting the login of the user this way
1607
        my $attributename = C4::Context->preference('shibbolethLoginAttribute');
1608
        my $attributevalue = $ENV{$attributename};
1609
1610
        # Then, we check if it matches a valid koha user
1611
        if ($shib_login) {
1612
            my ( $retval, $retcard, $retuserid ) = C4::Auth_with_Shibboleth::checkpw_shib( $dbh, $shib_login );    # EXTERNAL AUTH
1613
            ($retval) and return ( $retval, $retcard, $retuserid );
1614
            return 0;
1615
        }
1616
    }
1617
1618
    # INTERNAL AUTH
1560
    return checkpw_internal(@_)
1619
    return checkpw_internal(@_)
1561
}
1620
}
1562
1621
(-)a/C4/Auth_with_Shibboleth.pm (+100 lines)
Line 0 Link Here
1
package C4::Auth_with_Shibboleth;
2
3
# Copyright 2011 BibLibre
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
use C4::Debug;
24
use C4::Context;
25
use C4::Utils qw( :all );
26
use CGI;
27
28
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug);
29
30
BEGIN {
31
    require Exporter;
32
    $VERSION = 3.03;                                                                    # set the version for version checking
33
    $debug   = $ENV{DEBUG};
34
    @ISA     = qw(Exporter);
35
    @EXPORT  = qw(logout_shib login_shib_url checkpw_shib get_login_shib);
36
}
37
my $context = C4::Context->new() or die 'C4::Context->new failed';
38
my $protocol = "https://";
39
40
# Logout from Shibboleth
41
sub logout_shib {
42
    my ($query) = @_;
43
    my $uri = $protocol . $ENV{'SERVER_NAME'};
44
    print $query->redirect( $uri . "/Shibboleth.sso/Logout?return=$uri" );
45
}
46
47
# Returns Shibboleth login URL with callback to the requesting URL
48
sub login_shib_url {
49
50
    my ($query) = @_;
51
    my $param = $protocol . $ENV{'SERVER_NAME'} . $query->script_name();
52
    my $uri = $protocol . $ENV{'SERVER_NAME'} . "/Shibboleth.sso/Login?target=$param";
53
    return $uri;
54
}
55
56
# Returns shibboleth user login
57
sub get_login_shib {
58
59
    # In case of a Shibboleth authentication, we expect a shibboleth user attribute (defined in the shibbolethLoginAttribute)
60
    # to contain the login of the shibboleth-authenticated user
61
62
    # Shibboleth attributes are mapped into http environmement variables,
63
    # so we're getting the login of the user this way
64
65
    my $shibbolethLoginAttribute = C4::Context->preference('shibbolethLoginAttribute');
66
    $debug and warn "shibbolethLoginAttribute value: $shibbolethLoginAttribute";
67
    $debug and warn "$shibbolethLoginAttribute value: " . $ENV{$shibbolethLoginAttribute};
68
69
    return $ENV{$shibbolethLoginAttribute};
70
}
71
72
# Checks for password correctness
73
# In our case : does the given username matches one of our users ?
74
sub checkpw_shib {
75
    $debug and warn "checkpw_shib";
76
77
    my ( $dbh, $userid ) = @_;
78
    my $retnumber;
79
    $debug and warn "User Shibboleth-authenticated as: $userid";
80
81
    # Does it match one of our users ?
82
    my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
83
    $sth->execute($userid);
84
    if ( $sth->rows ) {
85
        $retnumber = $sth->fetchrow;
86
        return ( 1, $retnumber, $userid );
87
    }
88
    $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
89
    $sth->execute($userid);
90
    if ( $sth->rows ) {
91
        $retnumber = $sth->fetchrow;
92
        return ( 1, $retnumber, $userid );
93
    }
94
95
    # If we reach this point, the user is not a valid koha user
96
    $debug and warn "User $userid is not a valid Koha user";
97
    return 0;
98
}
99
100
1;
(-)a/installer/data/mysql/updatedatabase.pl (+8 lines)
Lines 8577-8582 if ( CheckVersion($DBversion) ) { Link Here
8577
    SetVersion ($DBversion);
8577
    SetVersion ($DBversion);
8578
}
8578
}
8579
8579
8580
$DBversion = "XXX";
8581
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
8582
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethAuthentication','','','Enable or disable Shibboleth authentication','YesNo')");
8583
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethLoginAttribute','','','Which shibboleth user attribute should be used to match koha user login?','')");
8584
    print "Upgrade to $DBversion done (Adds shibbolethAuthentication and shibbolethLoginAttribute preferences)\n";
8585
    SetVersion ($DBversion);
8586
}
8587
8580
=head1 FUNCTIONS
8588
=head1 FUNCTIONS
8581
8589
8582
=head2 TableExists($table)
8590
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref (+11 lines)
Lines 105-110 Administration: Link Here
105
                  yes: Allow
105
                  yes: Allow
106
                  no: "Don't Allow"
106
                  no: "Don't Allow"
107
            - Mozilla persona for login
107
            - Mozilla persona for login
108
    Shibboleth Authentication:
109
        -
110
            - pref: shibbolethAuthentication
111
              default: 0
112
              choices:
113
                  yes: Use
114
                  no: "Don't use"
115
            - Shibboleth for login authentication.
116
        -
117
            - Which shibboleth user attribute should be used to match koha user login?
118
            - pref: shibbolethLoginAttribute
108
    Search Engine:
119
    Search Engine:
109
        -
120
        -
110
            - pref: SearchEngine
121
            - pref: SearchEngine
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt (+16 lines)
Lines 46-51 Link Here
46
<p>You entered an incorrect username or password. Please try again! And remember, usernames and passwords are case sensitive.</p>
46
<p>You entered an incorrect username or password. Please try again! And remember, usernames and passwords are case sensitive.</p>
47
[% END %]
47
[% END %]
48
48
49
[% IF ( shibbolethAuthentication ) %]
50
<h4>Shibboleth Login</h4>
51
52
[% IF ( invalidShibLogin ) %]
53
<!-- This is what is displated if shibboleth login has failed -->
54
<p>Sorry, the shibboleth login failed.</p>
55
[% END %]
56
57
<p>If you have a shibboleth account,
58
please <a href="[% shibbolethLoginUrl %]">click here to login</a>.</p>
59
60
<h4>Local Login</h4>
61
<p>If you do not have a shibboleth account, but a local account, you can still log in : </p>
62
63
[% END %]
64
49
[% IF ( casAuthentication ) %]
65
[% IF ( casAuthentication ) %]
50
<h4>Cas login</h4>
66
<h4>Cas login</h4>
51
67
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt (+1 lines)
Lines 47-52 Link Here
47
    [% IF ( opacuserlogin ) %]
47
    [% IF ( opacuserlogin ) %]
48
    [% UNLESS ( loggedinusername ) %]
48
    [% UNLESS ( loggedinusername ) %]
49
    [% UNLESS ( casAuthentication ) %]
49
    [% UNLESS ( casAuthentication ) %]
50
    [% UNLESS ( shibbolethAuthentication ) %]
50
    <div id="login" class="container clearfix">
51
    <div id="login" class="container clearfix">
51
	<form action="/cgi-bin/koha/opac-user.pl" method="post" name="auth" id="auth">
52
	<form action="/cgi-bin/koha/opac-user.pl" method="post" name="auth" id="auth">
52
    <input type="hidden" name="koha_login_context" value="opac" />
53
    <input type="hidden" name="koha_login_context" value="opac" />
(-)a/opac/opac-main.pl (+2 lines)
Lines 44-49 $template->param( Link Here
44
    casAuthentication   => $casAuthentication,
44
    casAuthentication   => $casAuthentication,
45
);
45
);
46
46
47
my $shibbolethAuthentication = C4::Context->preference('shibbolethAuthentication');
48
$template->param( shibbolethAuthentication => $shibbolethAuthentication);
47
49
48
# display news
50
# display news
49
# use cookie setting for language, bug default to syspref if it's not set
51
# use cookie setting for language, bug default to syspref if it's not set
(-)a/opac/opac-user.pl (-1 / +3 lines)
Lines 72-77 for ( C4::Context->preference("OPACShowHoldQueueDetails") ) { Link Here
72
my $patronupdate = $query->param('patronupdate');
72
my $patronupdate = $query->param('patronupdate');
73
my $canrenew = 1;
73
my $canrenew = 1;
74
74
75
my $shibbolethAuthentication = C4::Context->preference('shibbolethAuthentication');
76
$template->param( shibbolethAuthentication => $shibbolethAuthentication );
77
75
# get borrower information ....
78
# get borrower information ....
76
my ( $borr ) = GetMemberDetails( $borrowernumber );
79
my ( $borr ) = GetMemberDetails( $borrowernumber );
77
80
78
- 

Return to bug 8446