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

(-)a/C4/Auth.pm (-8 / +68 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 651-658 sub checkauth { Link Here
651
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
658
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
652
    my $casparam = $query->param('cas');
659
    my $casparam = $query->param('cas');
653
660
654
    if ( $userid = $ENV{'REMOTE_USER'} ) {
661
    # Basic authentication is incompatible with the use of Shibboleth,
655
            # Using Basic Authentication, no cookies required
662
    # as Shibboleth may return REMOTE_USER as a Shibboleth attribute,
663
    # and it may not be the attribute we want to use to match the koha login.
664
    #
665
    # Also, do not consider an empty REMOTE_USER.
666
    #
667
    # Finally, after those tests, we can assume (although if it would be better with
668
    # a syspref) that if we get a REMOTE_USER, that's from basic authentication,
669
    # and we can affect it to $userid.
670
    if ( !$shib and $ENV{'REMOTE_USER'} ne '' and $userid = $ENV{'REMOTE_USER'} ) {
671
672
        # Using Basic Authentication, no cookies required
656
        $cookie = $query->cookie(
673
        $cookie = $query->cookie(
657
            -name     => 'CGISESSID',
674
            -name     => 'CGISESSID',
658
            -value    => '',
675
            -value    => '',
Lines 707-717 sub checkauth { Link Here
707
            $sessionID = undef;
724
            $sessionID = undef;
708
            $userid    = undef;
725
            $userid    = undef;
709
726
710
        if ($cas and $caslogout) {
727
            if ($cas and $caslogout) {
711
        logout_cas($query);
728
                logout_cas($query);
712
        }
729
            }
730
731
            # If we are in a shibboleth session (shibboleth is enabled, and a shibboleth username is set)
732
            if ( $shib and $shib_login and $type eq 'opac') {
733
            # (Note: $type eq 'opac' condition should be removed when shibboleth authentication for intranet will be implemented)
734
                logout_shib($query);
735
            }
713
        }
736
        }
714
        elsif ( $lasttime < time() - $timeout ) {
737
        elsif ( $lasttime < time() - $timeout ) {
738
715
            # timed logout
739
            # timed logout
716
            $info{'timed_out'} = 1;
740
            $info{'timed_out'} = 1;
717
            $session->delete() if $session;
741
            $session->delete() if $session;
Lines 759-774 sub checkauth { Link Here
759
            -value    => $session->id,
783
            -value    => $session->id,
760
            -HttpOnly => 1
784
            -HttpOnly => 1
761
        );
785
        );
762
    $userid = $query->param('userid');
786
        $userid = $query->param('userid');
763
        if (   ( $cas && $query->param('ticket') )
787
        if (   ( $cas && $query->param('ticket') )
764
            || $userid
788
            || $userid
789
            || $shib
765
            || ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne
790
            || ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne
766
            'None' || $persona )
791
            'None' || $persona )
767
        {
792
        {
768
            my $password = $query->param('password');
793
            my $password = $query->param('password');
769
794
770
            my ( $return, $cardnumber );
795
            my ( $return, $cardnumber );
771
            if ( $cas && $query->param('ticket') ) {
796
            if ($shib && $shib_login && $type eq 'opac' && !$password) {
797
                my $retuserid;
798
                ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
799
                $userid = $retuserid;
800
                $info{'invalidShibLogin'} = 1 unless ($return);
801
802
            } elsif ( $cas && $query->param('ticket') ) {
772
                my $retuserid;
803
                my $retuserid;
773
                ( $return, $cardnumber, $retuserid ) =
804
                ( $return, $cardnumber, $retuserid ) =
774
                  checkpw( $dbh, $userid, $password, $query );
805
                  checkpw( $dbh, $userid, $password, $query );
Lines 1013-1018 sub checkauth { Link Here
1013
        login                => 1,
1044
        login                => 1,
1014
        INPUTS               => \@inputs,
1045
        INPUTS               => \@inputs,
1015
        casAuthentication    => C4::Context->preference("casAuthentication"),
1046
        casAuthentication    => C4::Context->preference("casAuthentication"),
1047
        shibbolethAuthentication => C4::Context->preference("shibbolethAuthentication"),
1016
        suggestion           => C4::Context->preference("suggestion"),
1048
        suggestion           => C4::Context->preference("suggestion"),
1017
        virtualshelves       => C4::Context->preference("virtualshelves"),
1049
        virtualshelves       => C4::Context->preference("virtualshelves"),
1018
        LibraryName          => "" . C4::Context->preference("LibraryName"),
1050
        LibraryName          => "" . C4::Context->preference("LibraryName"),
Lines 1084-1089 sub checkauth { Link Here
1084
        );
1116
        );
1085
    }
1117
    }
1086
1118
1119
    if ($shib) {
1120
            $template->param(
1121
                shibbolethLoginUrl    => login_shib_url($query),
1122
            );
1123
    }
1124
1087
    my $self_url = $query->url( -absolute => 1 );
1125
    my $self_url = $query->url( -absolute => 1 );
1088
    $template->param(
1126
    $template->param(
1089
        url         => $self_url,
1127
        url         => $self_url,
Lines 1510-1515 sub checkpw { Link Here
1510
        return 0;
1548
        return 0;
1511
    }
1549
    }
1512
1550
1551
    # If we are in a shibboleth session (shibboleth is enabled and no password has been provided)
1552
    if ($shib && !$password) {
1553
1554
        $debug and print STDERR "## checkpw - checking Shibboleth\n";
1555
        # In case of a Shibboleth authentication, we expect a shibboleth user attribute
1556
        # (defined in the shibbolethLoginAttribute) tto contain the login of the
1557
        # shibboleth-authenticated user
1558
1559
        # Shibboleth attributes are mapped into http environmement variables,
1560
        # so we're getting the login of the user this way
1561
        my $attributename = C4::Context->preference('shibbolethLoginAttribute');
1562
        my $attributevalue = $ENV{$attributename};
1563
1564
        # Then, we check if it matches a valid koha user
1565
        if ($shib_login) {
1566
            my ( $retval, $retcard, $retuserid ) = C4::Auth_with_Shibboleth::checkpw_shib( $dbh, $shib_login );    # EXTERNAL AUTH
1567
            ($retval) and return ( $retval, $retcard, $retuserid );
1568
            return 0;
1569
        }
1570
    }
1571
1572
    # INTERNAL AUTH
1513
    return checkpw_internal(@_)
1573
    return checkpw_internal(@_)
1514
}
1574
}
1515
1575
(-)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 7778-7783 if(CheckVersion($DBversion)) { Link Here
7778
    SetVersion($DBversion);
7778
    SetVersion($DBversion);
7779
}
7779
}
7780
7780
7781
$DBversion = "XXX";
7782
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
7783
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethAuthentication','','','Enable or disable Shibboleth authentication','YesNo')");
7784
    $dbh->do("INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES('shibbolethLoginAttribute','','','Which shibboleth user attribute should be used to match koha user login?','')");
7785
    print "Upgrade to $DBversion done (Adds shibbolethAuthentication and shibbolethLoginAttribute preferences)\n";
7786
    SetVersion ($DBversion);
7787
}
7788
7781
=head1 FUNCTIONS
7789
=head1 FUNCTIONS
7782
7790
7783
=head2 TableExists($table)
7791
=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.002';
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