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

(-)a/C4/Auth.pm (-12 / +52 lines)
Lines 748-754 sub _timeout_syspref { Link Here
748
sub checkauth {
748
sub checkauth {
749
    my $query = shift;
749
    my $query = shift;
750
    $debug and warn "Checking Auth";
750
    $debug and warn "Checking Auth";
751
752
    # $authnotrequired will be set for scripts which will run without authentication
751
    # $authnotrequired will be set for scripts which will run without authentication
753
    my $authnotrequired = shift;
752
    my $authnotrequired = shift;
754
    my $flagsrequired   = shift;
753
    my $flagsrequired   = shift;
Lines 768-774 sub checkauth { Link Here
768
    my $logout = $query->param('logout.x');
767
    my $logout = $query->param('logout.x');
769
768
770
    my $anon_search_history;
769
    my $anon_search_history;
771
770
    my $cas_ticket = '';
772
    # This parameter is the name of the CAS server we want to authenticate against,
771
    # This parameter is the name of the CAS server we want to authenticate against,
773
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
772
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
774
    my $casparam = $query->param('cas');
773
    my $casparam = $query->param('cas');
Lines 906-913 sub checkauth { Link Here
906
            }
905
            }
907
        }
906
        }
908
    }
907
    }
908
    elsif ($logout && $cas) {
909
        # We got a cas single logout request from a cas server;
910
        my $ticket = $query->param('cas_ticket');
911
        # We've been called as part of the single logout destroy the session associated with the cas ticket
912
        my $storage_method = C4::Context->preference('SessionStorage');
913
        my $dsn;
914
        my $dsn_options;
915
        # shift this to a function make get_session use the function too
916
        my $dbh            = C4::Context->dbh;
917
        if ( $storage_method eq 'mysql' ) {
918
            $dsn = "driver:MySQL;serializer:yaml;id:md5";
919
            $dsn_options = { Handle => $dbh };
920
        }
921
        elsif (  $storage_method eq 'Pg' ) {
922
            $dsn = "driver:PostgreSQL;serializer:yaml;id:md5";
923
            $dsn_options = { Handle => $dbh };
924
        }
925
        elsif ( $storage_method eq 'memcached' && Koha::Caches->get_instance->memcached_cache ) {
926
            $dsn = "driver:memcached;serializer:yaml;id:md5";
927
            my $memcached = Koha::Caches->get_instance()->memcached_cache;
928
            $dsn_options =  { Memcached => $memcached };
929
        }
930
        else {
931
            $dsn = "driver:File;serializer:yaml;id:md5";
932
            my $dir = File::Spec->tmpdir;
933
            my $instance = C4::Context->config( 'database' ); #actually for packages not exactly the instance name, but generally safer to leave it as it is
934
            $dsn_options =  { Directory => "$dir/cgisess_$instance" };
935
        }
936
        my $success =  CGI::Session->find( $dsn, sub {delete_cas_session(@_, $ticket)}, $dsn_options );
937
        sub delete_cas_session {
938
            my $session = shift;
939
            my $ticket = shift;
940
            if ($session->param('cas_ticket') && $session->param('cas_ticket') eq $ticket ) {
941
                $session->delete;
942
                $session->flush;
943
            }
944
        }
945
    }
909
    unless ( $userid || $sessionID ) {
946
    unless ( $userid || $sessionID ) {
910
911
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
947
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
912
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
948
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
913
949
Lines 938-944 sub checkauth { Link Here
938
        {
974
        {
939
            my $password    = $query->param('password');
975
            my $password    = $query->param('password');
940
            my $shibSuccess = 0;
976
            my $shibSuccess = 0;
941
942
            my ( $return, $cardnumber );
977
            my ( $return, $cardnumber );
943
978
944
            # If shib is enabled and we have a shib login, does the login match a valid koha user
979
            # If shib is enabled and we have a shib login, does the login match a valid koha user
Lines 956-962 sub checkauth { Link Here
956
            unless ($shibSuccess) {
991
            unless ($shibSuccess) {
957
                if ( $cas && $query->param('ticket') ) {
992
                if ( $cas && $query->param('ticket') ) {
958
                    my $retuserid;
993
                    my $retuserid;
959
                    ( $return, $cardnumber, $retuserid ) =
994
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
960
                      checkpw( $dbh, $userid, $password, $query, $type );
995
                      checkpw( $dbh, $userid, $password, $query, $type );
961
                    $userid = $retuserid;
996
                    $userid = $retuserid;
962
                    $info{'invalidCasLogin'} = 1 unless ($return);
997
                    $info{'invalidCasLogin'} = 1 unless ($return);
Lines 1016-1022 sub checkauth { Link Here
1016
                }
1051
                }
1017
                else {
1052
                else {
1018
                    my $retuserid;
1053
                    my $retuserid;
1019
                    ( $return, $cardnumber, $retuserid ) =
1054
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1020
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1055
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1021
                    $userid = $retuserid if ($retuserid);
1056
                    $userid = $retuserid if ($retuserid);
1022
                    $info{'invalid_username_or_password'} = 1 unless ($return);
1057
                    $info{'invalid_username_or_password'} = 1 unless ($return);
Lines 1142-1147 sub checkauth { Link Here
1142
                    $session->param( 'ip',           $session->remote_addr() );
1177
                    $session->param( 'ip',           $session->remote_addr() );
1143
                    $session->param( 'lasttime',     time() );
1178
                    $session->param( 'lasttime',     time() );
1144
                }
1179
                }
1180
                $session->param('cas_ticket', $cas_ticket) if $cas_ticket;
1145
                C4::Context->set_userenv(
1181
                C4::Context->set_userenv(
1146
                    $session->param('number'),       $session->param('id'),
1182
                    $session->param('number'),       $session->param('id'),
1147
                    $session->param('cardnumber'),   $session->param('firstname'),
1183
                    $session->param('cardnumber'),   $session->param('firstname'),
Lines 1374-1382 Possible return values in C<$status> are: Link Here
1374
=cut
1410
=cut
1375
1411
1376
sub check_api_auth {
1412
sub check_api_auth {
1413
1377
    my $query         = shift;
1414
    my $query         = shift;
1378
    my $flagsrequired = shift;
1415
    my $flagsrequired = shift;
1379
1380
    my $dbh     = C4::Context->dbh;
1416
    my $dbh     = C4::Context->dbh;
1381
    my $timeout = _timeout_syspref();
1417
    my $timeout = _timeout_syspref();
1382
1418
Lines 1470-1476 sub check_api_auth { Link Here
1470
        # new login
1506
        # new login
1471
        my $userid   = $query->param('userid');
1507
        my $userid   = $query->param('userid');
1472
        my $password = $query->param('password');
1508
        my $password = $query->param('password');
1473
        my ( $return, $cardnumber );
1509
        my ( $return, $cardnumber, $cas_ticket );
1474
1510
1475
        # Proxy CAS auth
1511
        # Proxy CAS auth
1476
        if ( $cas && $query->param('PT') ) {
1512
        if ( $cas && $query->param('PT') ) {
Lines 1479-1485 sub check_api_auth { Link Here
1479
1515
1480
            # In case of a CAS authentication, we use the ticket instead of the password
1516
            # In case of a CAS authentication, we use the ticket instead of the password
1481
            my $PT = $query->param('PT');
1517
            my $PT = $query->param('PT');
1482
            ( $return, $cardnumber, $userid ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1518
            ( $return, $cardnumber, $userid, $cas_ticket ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1483
        } else {
1519
        } else {
1484
1520
1485
            # User / password auth
1521
            # User / password auth
Lines 1488-1494 sub check_api_auth { Link Here
1488
                # caller did something wrong, fail the authenticateion
1524
                # caller did something wrong, fail the authenticateion
1489
                return ( "failed", undef, undef );
1525
                return ( "failed", undef, undef );
1490
            }
1526
            }
1491
            ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query );
1527
            my $newuserid;
1528
            ( $return, $cardnumber, $newuserid, $cas_ticket ) = checkpw( $dbh, $userid, $password, $query );
1492
        }
1529
        }
1493
1530
1494
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
1531
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
Lines 1586-1591 sub check_api_auth { Link Here
1586
                $session->param( 'ip',           $session->remote_addr() );
1623
                $session->param( 'ip',           $session->remote_addr() );
1587
                $session->param( 'lasttime',     time() );
1624
                $session->param( 'lasttime',     time() );
1588
            }
1625
            }
1626
            $session->param( 'cas_ticket', $cas_ticket);
1589
            C4::Context->set_userenv(
1627
            C4::Context->set_userenv(
1590
                $session->param('number'),       $session->param('id'),
1628
                $session->param('number'),       $session->param('id'),
1591
                $session->param('cardnumber'),   $session->param('firstname'),
1629
                $session->param('cardnumber'),   $session->param('firstname'),
Lines 1792-1800 sub checkpw { Link Here
1792
        # In case of a CAS authentication, we use the ticket instead of the password
1830
        # In case of a CAS authentication, we use the ticket instead of the password
1793
        my $ticket = $query->param('ticket');
1831
        my $ticket = $query->param('ticket');
1794
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1832
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1795
        my ( $retval, $retcard, $retuserid ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1833
        my ( $retval, $retcard, $retuserid, $cas_ticket ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1796
        if ( $retval ) {
1834
        if ( $retval ) {
1797
            @return = ( $retval, $retcard, $retuserid );
1835
            @return = ( $retval, $retcard, $retuserid, $cas_ticket );
1836
        } else {
1837
            @return = (0);
1798
        }
1838
        }
1799
        $passwd_ok = $retval;
1839
        $passwd_ok = $retval;
1800
    }
1840
    }
(-)a/C4/Auth_with_cas.pm (-4 / +8 lines)
Lines 105-122 sub checkpw_cas { Link Here
105
            my $userid = $val->user();
105
            my $userid = $val->user();
106
            $debug and warn "User CAS authenticated as: $userid";
106
            $debug and warn "User CAS authenticated as: $userid";
107
107
108
            # we should store the CAS ticekt too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
109
108
            # Does it match one of our users ?
110
            # Does it match one of our users ?
109
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
111
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
110
            $sth->execute($userid);
112
            $sth->execute($userid);
111
            if ( $sth->rows ) {
113
            if ( $sth->rows ) {
112
                $retnumber = $sth->fetchrow;
114
                $retnumber = $sth->fetchrow;
113
                return ( 1, $retnumber, $userid );
115
                return ( 1, $retnumber, $userid, $ticket );
114
            }
116
            }
115
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
117
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
116
            $sth->execute($userid);
118
            $sth->execute($userid);
117
            if ( $sth->rows ) {
119
            if ( $sth->rows ) {
118
                $retnumber = $sth->fetchrow;
120
                $retnumber = $sth->fetchrow;
119
                return ( 1, $retnumber, $userid );
121
                return ( 1, $retnumber, $userid, $ticket );
120
            }
122
            }
121
123
122
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
124
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
Lines 154-172 sub check_api_auth_cas { Link Here
154
156
155
            my $userid = $r->user;
157
            my $userid = $r->user;
156
158
159
            # we should store the CAS ticket too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
160
157
            # Does it match one of our users ?
161
            # Does it match one of our users ?
158
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
162
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
159
            $sth->execute($userid);
163
            $sth->execute($userid);
160
            if ( $sth->rows ) {
164
            if ( $sth->rows ) {
161
                $retnumber = $sth->fetchrow;
165
                $retnumber = $sth->fetchrow;
162
                return ( 1, $retnumber, $userid );
166
                return ( 1, $retnumber, $userid, $PT );
163
            }
167
            }
164
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
168
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
165
            return $r->user;
169
            return $r->user;
166
            $sth->execute($userid);
170
            $sth->execute($userid);
167
            if ( $sth->rows ) {
171
            if ( $sth->rows ) {
168
                $retnumber = $sth->fetchrow;
172
                $retnumber = $sth->fetchrow;
169
                return ( 1, $retnumber, $userid );
173
                return ( 1, $retnumber, $userid, $PT );
170
            }
174
            }
171
175
172
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
176
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
(-)a/opac/opac-user.pl (-1 / +22 lines)
Lines 61-66 BEGIN { Link Here
61
        import C4::External::BakerTaylor qw(&image_url &link_url);
61
        import C4::External::BakerTaylor qw(&image_url &link_url);
62
    }
62
    }
63
}
63
}
64
my $logout='';
65
# CAS Single Sign Out
66
if (C4::Context->preference('casAuthentication')){
67
    # Check we havent been hit by a logout call
68
    my $xml = $query->param('logoutRequest');
69
    if ($xml) {
70
        my $dom = XML::LibXML->load_xml(string => $xml);
71
        my $ticket;
72
        foreach my $node ($dom->findnodes('/samlp:LogoutRequest')){
73
            $ticket = $node->findvalue('./samlp:SessionIndex');
74
        }
75
        $query->param(-name =>'logout.x', -value => 1);
76
        $query->param(-name =>'cas_ticket', -value => $ticket);
77
        $logout=1;
78
    }
79
}
64
80
65
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
81
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
66
    {
82
    {
Lines 72-77 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
72
    }
88
    }
73
);
89
);
74
90
91
if ($logout){
92
    print $query->header;
93
    exit;
94
}
95
96
75
my %renewed = map { $_ => 1 } split( ':', $query->param('renewed') );
97
my %renewed = map { $_ => 1 } split( ':', $query->param('renewed') );
76
98
77
my $show_priority;
99
my $show_priority;
78
- 

Return to bug 19160