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

(-)a/C4/Auth.pm (-8 / +67 lines)
Lines 34-40 use POSIX qw/strftime/; Link Here
34
use List::MoreUtils qw/ any /;
34
use List::MoreUtils qw/ any /;
35
35
36
# use utf8;
36
# use utf8;
37
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout);
37
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout $shib $shib_login);
38
38
39
BEGIN {
39
BEGIN {
40
    sub psgi_env { any { /^psgi\./ } keys %ENV }
40
    sub psgi_env { any { /^psgi\./ } keys %ENV }
Lines 54-65 BEGIN { Link Here
54
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
54
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
55
    $ldap        = C4::Context->config('useldapserver') || 0;
55
    $ldap        = C4::Context->config('useldapserver') || 0;
56
    $cas         = C4::Context->preference('casAuthentication');
56
    $cas         = C4::Context->preference('casAuthentication');
57
    $shib        = C4::Context->preference('shibbolethAuthentication');
57
    $caslogout   = C4::Context->preference('casLogout');
58
    $caslogout   = C4::Context->preference('casLogout');
58
    require C4::Auth_with_cas;             # no import
59
    require C4::Auth_with_cas;             # no import
60
    require C4::Auth_with_Shibboleth;
59
    if ($ldap) {
61
    if ($ldap) {
60
    require C4::Auth_with_ldap;
62
    require C4::Auth_with_ldap;
61
    import C4::Auth_with_ldap qw(checkpw_ldap);
63
    import C4::Auth_with_ldap qw(checkpw_ldap);
62
    }
64
    }
65
    if ($shib) {
66
        import C4::Auth_with_Shibboleth qw(checkpw_shib logout_shib login_shib_url get_login_shib);
67
        # Getting user login
68
        $shib_login = get_login_shib();
69
    }
63
    if ($cas) {
70
    if ($cas) {
64
        import  C4::Auth_with_cas qw(check_api_auth_cas checkpw_cas login_cas logout_cas login_cas_url);
71
        import  C4::Auth_with_cas qw(check_api_auth_cas checkpw_cas login_cas logout_cas login_cas_url);
65
    }
72
    }
Lines 649-656 sub checkauth { Link Here
649
    my $casparam = $query->param('cas');
656
    my $casparam = $query->param('cas');
650
    my $q_userid = $query->param('userid') // '';
657
    my $q_userid = $query->param('userid') // '';
651
658
652
    if ( $userid = $ENV{'REMOTE_USER'} ) {
659
    # Basic authentication is incompatible with the use of Shibboleth,
653
            # Using Basic Authentication, no cookies required
660
    # as Shibboleth may return REMOTE_USER as a Shibboleth attribute,
661
    # and it may not be the attribute we want to use to match the koha login.
662
    #
663
    # Also, do not consider an empty REMOTE_USER.
664
    #
665
    # Finally, after those tests, we can assume (although if it would be better with
666
    # a syspref) that if we get a REMOTE_USER, that's from basic authentication,
667
    # and we can affect it to $userid.
668
    if ( !$shib and $ENV{'REMOTE_USER'} ne '' and $userid = $ENV{'REMOTE_USER'} ) {
669
670
        # Using Basic Authentication, no cookies required
654
        $cookie = $query->cookie(
671
        $cookie = $query->cookie(
655
            -name     => 'CGISESSID',
672
            -name     => 'CGISESSID',
656
            -value    => '',
673
            -value    => '',
Lines 708-716 sub checkauth { Link Here
708
            $sessionID = undef;
725
            $sessionID = undef;
709
            $userid    = undef;
726
            $userid    = undef;
710
727
711
        if ($cas and $caslogout) {
728
            if ($cas and $caslogout) {
712
        logout_cas($query);
729
                logout_cas($query);
713
        }
730
            }
731
732
            # If we are in a shibboleth session (shibboleth is enabled, and a shibboleth username is set)
733
            if ( $shib and $shib_login and $type eq 'opac') {
734
            # (Note: $type eq 'opac' condition should be removed when shibboleth authentication for intranet will be implemented)
735
                logout_shib($query);
736
            }
714
        }
737
        }
715
        elsif ( !$lasttime || ($lasttime < time() - $timeout) ) {
738
        elsif ( !$lasttime || ($lasttime < time() - $timeout) ) {
716
            # timed logout
739
            # timed logout
Lines 780-792 sub checkauth { Link Here
780
        }
803
        }
781
        if (   ( $cas && $query->param('ticket') )
804
        if (   ( $cas && $query->param('ticket') )
782
            || $userid
805
            || $userid
806
            || $shib
783
            || $pki_field ne 'None'
807
            || $pki_field ne 'None'
784
            || $persona )
808
	    || $persona )
785
        {
809
        {
786
            my $password = $query->param('password');
810
            my $password = $query->param('password');
787
811
788
            my ( $return, $cardnumber );
812
            my ( $return, $cardnumber );
789
            if ( $cas && $query->param('ticket') ) {
813
            if ($shib && $shib_login && $type eq 'opac' && !$password) {
814
                my $retuserid;
815
                ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
816
                $userid = $retuserid;
817
                $info{'invalidShibLogin'} = 1 unless ($return);
818
819
            } elsif ( $cas && $query->param('ticket') ) {
790
                my $retuserid;
820
                my $retuserid;
791
                ( $return, $cardnumber, $retuserid ) =
821
                ( $return, $cardnumber, $retuserid ) =
792
                  checkpw( $dbh, $userid, $password, $query );
822
                  checkpw( $dbh, $userid, $password, $query );
Lines 1033-1038 sub checkauth { Link Here
1033
        login                => 1,
1063
        login                => 1,
1034
        INPUTS               => \@inputs,
1064
        INPUTS               => \@inputs,
1035
        casAuthentication    => C4::Context->preference("casAuthentication"),
1065
        casAuthentication    => C4::Context->preference("casAuthentication"),
1066
        shibbolethAuthentication => C4::Context->preference("shibbolethAuthentication"),
1036
        suggestion           => C4::Context->preference("suggestion"),
1067
        suggestion           => C4::Context->preference("suggestion"),
1037
        virtualshelves       => C4::Context->preference("virtualshelves"),
1068
        virtualshelves       => C4::Context->preference("virtualshelves"),
1038
        LibraryName          => "" . C4::Context->preference("LibraryName"),
1069
        LibraryName          => "" . C4::Context->preference("LibraryName"),
Lines 1104-1109 sub checkauth { Link Here
1104
        );
1135
        );
1105
    }
1136
    }
1106
1137
1138
    if ($shib) {
1139
            $template->param(
1140
                shibbolethLoginUrl    => login_shib_url($query),
1141
            );
1142
    }
1143
1107
    my $self_url = $query->url( -absolute => 1 );
1144
    my $self_url = $query->url( -absolute => 1 );
1108
    $template->param(
1145
    $template->param(
1109
        url         => $self_url,
1146
        url         => $self_url,
Lines 1536-1541 sub checkpw { Link Here
1536
        return 0;
1573
        return 0;
1537
    }
1574
    }
1538
1575
1576
    # If we are in a shibboleth session (shibboleth is enabled and no password has been provided)
1577
    if ($shib && !$password) {
1578
1579
        $debug and print STDERR "## checkpw - checking Shibboleth\n";
1580
        # In case of a Shibboleth authentication, we expect a shibboleth user attribute
1581
        # (defined in the shibbolethLoginAttribute) tto contain the login of the
1582
        # shibboleth-authenticated user
1583
1584
        # Shibboleth attributes are mapped into http environmement variables,
1585
        # so we're getting the login of the user this way
1586
        my $attributename = C4::Context->preference('shibbolethLoginAttribute');
1587
        my $attributevalue = $ENV{$attributename};
1588
1589
        # Then, we check if it matches a valid koha user
1590
        if ($shib_login) {
1591
            my ( $retval, $retcard, $retuserid ) = C4::Auth_with_Shibboleth::checkpw_shib( $dbh, $shib_login );    # EXTERNAL AUTH
1592
            ($retval) and return ( $retval, $retcard, $retuserid );
1593
            return 0;
1594
        }
1595
    }
1596
1597
    # INTERNAL AUTH
1539
    return checkpw_internal(@_)
1598
    return checkpw_internal(@_)
1540
}
1599
}
1541
1600
(-)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 8012-8017 if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { Link Here
8012
    SetVersion($DBversion);
8012
    SetVersion($DBversion);
8013
}
8013
}
8014
8014
8015
$DBversion = "XXX";
8016
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
8017
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethAuthentication','','','Enable or disable Shibboleth authentication','YesNo')");
8018
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethLoginAttribute','','','Which shibboleth user attribute should be used to match koha user login?','')");
8019
    print "Upgrade to $DBversion done (Adds shibbolethAuthentication and shibbolethLoginAttribute preferences)\n";
8020
    SetVersion ($DBversion);
8021
}
8022
8015
=head1 FUNCTIONS
8023
=head1 FUNCTIONS
8016
8024
8017
=head2 TableExists($table)
8025
=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/kohaversion.pl (-1 / +1 lines)
Lines 16-22 the kohaversion is divided in 4 parts : Link Here
16
use strict;
16
use strict;
17
17
18
sub kohaversion {
18
sub kohaversion {
19
    our $VERSION = '3.15.00.019';
19
    our $VERSION = 'XXX';
20
    # version needs to be set this way
20
    # version needs to be set this way
21
    # so that it can be picked up by Makefile.PL
21
    # so that it can be picked up by Makefile.PL
22
    # during install
22
    # during install
(-)a/opac/opac-main.pl (+2 lines)
Lines 43-48 $template->param( Link Here
43
    casAuthentication   => $casAuthentication,
43
    casAuthentication   => $casAuthentication,
44
);
44
);
45
45
46
my $shibbolethAuthentication = C4::Context->preference('shibbolethAuthentication');
47
$template->param( shibbolethAuthentication => $shibbolethAuthentication);
46
48
47
# display news
49
# display news
48
# use cookie setting for language, bug default to syspref if it's not set
50
# use cookie setting for language, bug default to syspref if it's not set
(-)a/opac/opac-user.pl (-1 / +3 lines)
Lines 71-76 for ( C4::Context->preference("OPACShowHoldQueueDetails") ) { Link Here
71
my $patronupdate = $query->param('patronupdate');
71
my $patronupdate = $query->param('patronupdate');
72
my $canrenew = 1;
72
my $canrenew = 1;
73
73
74
my $shibbolethAuthentication = C4::Context->preference('shibbolethAuthentication');
75
$template->param( shibbolethAuthentication => $shibbolethAuthentication );
76
74
# get borrower information ....
77
# get borrower information ....
75
my ( $borr ) = GetMemberDetails( $borrowernumber );
78
my ( $borr ) = GetMemberDetails( $borrowernumber );
76
79
77
- 

Return to bug 8446