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

(-)a/C4/Auth.pm (-12 / +52 lines)
Lines 745-751 sub _timeout_syspref { Link Here
745
sub checkauth {
745
sub checkauth {
746
    my $query = shift;
746
    my $query = shift;
747
    $debug and warn "Checking Auth";
747
    $debug and warn "Checking Auth";
748
749
    # $authnotrequired will be set for scripts which will run without authentication
748
    # $authnotrequired will be set for scripts which will run without authentication
750
    my $authnotrequired = shift;
749
    my $authnotrequired = shift;
751
    my $flagsrequired   = shift;
750
    my $flagsrequired   = shift;
Lines 765-771 sub checkauth { Link Here
765
    my $logout = $query->param('logout.x');
764
    my $logout = $query->param('logout.x');
766
765
767
    my $anon_search_history;
766
    my $anon_search_history;
768
767
    my $cas_ticket = '';
769
    # This parameter is the name of the CAS server we want to authenticate against,
768
    # This parameter is the name of the CAS server we want to authenticate against,
770
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
769
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
771
    my $casparam = $query->param('cas');
770
    my $casparam = $query->param('cas');
Lines 903-910 sub checkauth { Link Here
903
            }
902
            }
904
        }
903
        }
905
    }
904
    }
905
    elsif ($logout && $cas) {
906
        # We got a cas single logout request from a cas server;
907
        my $ticket = $query->param('cas_ticket');
908
        # We've been called as part of the single logout destroy the session associated with the cas ticket
909
        my $storage_method = C4::Context->preference('SessionStorage');
910
        my $dsn;
911
        my $dsn_options;
912
        # shift this to a function make get_session use the function too
913
        my $dbh            = C4::Context->dbh;
914
        if ( $storage_method eq 'mysql' ) {
915
            $dsn = "driver:MySQL;serializer:yaml;id:md5";
916
            $dsn_options = { Handle => $dbh };
917
        }
918
        elsif (  $storage_method eq 'Pg' ) {
919
            $dsn = "driver:PostgreSQL;serializer:yaml;id:md5";
920
            $dsn_options = { Handle => $dbh };
921
        }
922
        elsif ( $storage_method eq 'memcached' && Koha::Caches->get_instance->memcached_cache ) {
923
            $dsn = "driver:memcached;serializer:yaml;id:md5";
924
            my $memcached = Koha::Caches->get_instance()->memcached_cache;
925
            $dsn_options =  { Memcached => $memcached };
926
        }
927
        else {
928
            $dsn = "driver:File;serializer:yaml;id:md5";
929
            my $dir = File::Spec->tmpdir;
930
            my $instance = C4::Context->config( 'database' ); #actually for packages not exactly the instance name, but generally safer to leave it as it is
931
            $dsn_options =  { Directory => "$dir/cgisess_$instance" };
932
        }       
933
        my $success =  CGI::Session->find( $dsn, sub {delete_cas_session(@_, $ticket)}, $dsn_options );
934
        sub delete_cas_session {
935
            my $session = shift;
936
            my $ticket = shift;
937
            if ($session->param('cas_ticket') && $session->param('cas_ticket') eq $ticket ) {
938
                $session->delete;
939
                $session->flush;
940
            }
941
        }
942
    }
906
    unless ( $userid || $sessionID ) {
943
    unless ( $userid || $sessionID ) {
907
908
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
944
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
909
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
945
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
910
946
Lines 935-941 sub checkauth { Link Here
935
        {
971
        {
936
            my $password    = $query->param('password');
972
            my $password    = $query->param('password');
937
            my $shibSuccess = 0;
973
            my $shibSuccess = 0;
938
939
            my ( $return, $cardnumber );
974
            my ( $return, $cardnumber );
940
975
941
            # If shib is enabled and we have a shib login, does the login match a valid koha user
976
            # If shib is enabled and we have a shib login, does the login match a valid koha user
Lines 953-959 sub checkauth { Link Here
953
            unless ($shibSuccess) {
988
            unless ($shibSuccess) {
954
                if ( $cas && $query->param('ticket') ) {
989
                if ( $cas && $query->param('ticket') ) {
955
                    my $retuserid;
990
                    my $retuserid;
956
                    ( $return, $cardnumber, $retuserid ) =
991
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
957
                      checkpw( $dbh, $userid, $password, $query, $type );
992
                      checkpw( $dbh, $userid, $password, $query, $type );
958
                    $userid = $retuserid;
993
                    $userid = $retuserid;
959
                    $info{'invalidCasLogin'} = 1 unless ($return);
994
                    $info{'invalidCasLogin'} = 1 unless ($return);
Lines 1013-1019 sub checkauth { Link Here
1013
                }
1048
                }
1014
                else {
1049
                else {
1015
                    my $retuserid;
1050
                    my $retuserid;
1016
                    ( $return, $cardnumber, $retuserid ) =
1051
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1017
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1052
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1018
                    $userid = $retuserid if ($retuserid);
1053
                    $userid = $retuserid if ($retuserid);
1019
                    $info{'invalid_username_or_password'} = 1 unless ($return);
1054
                    $info{'invalid_username_or_password'} = 1 unless ($return);
Lines 1139-1144 sub checkauth { Link Here
1139
                    $session->param( 'ip',           $session->remote_addr() );
1174
                    $session->param( 'ip',           $session->remote_addr() );
1140
                    $session->param( 'lasttime',     time() );
1175
                    $session->param( 'lasttime',     time() );
1141
                }
1176
                }
1177
                $session->param('cas_ticket', $cas_ticket) if $cas_ticket;
1142
                C4::Context->set_userenv(
1178
                C4::Context->set_userenv(
1143
                    $session->param('number'),       $session->param('id'),
1179
                    $session->param('number'),       $session->param('id'),
1144
                    $session->param('cardnumber'),   $session->param('firstname'),
1180
                    $session->param('cardnumber'),   $session->param('firstname'),
Lines 1370-1378 Possible return values in C<$status> are: Link Here
1370
=cut
1406
=cut
1371
1407
1372
sub check_api_auth {
1408
sub check_api_auth {
1409
    
1373
    my $query         = shift;
1410
    my $query         = shift;
1374
    my $flagsrequired = shift;
1411
    my $flagsrequired = shift;
1375
1376
    my $dbh     = C4::Context->dbh;
1412
    my $dbh     = C4::Context->dbh;
1377
    my $timeout = _timeout_syspref();
1413
    my $timeout = _timeout_syspref();
1378
1414
Lines 1466-1472 sub check_api_auth { Link Here
1466
        # new login
1502
        # new login
1467
        my $userid   = $query->param('userid');
1503
        my $userid   = $query->param('userid');
1468
        my $password = $query->param('password');
1504
        my $password = $query->param('password');
1469
        my ( $return, $cardnumber );
1505
        my ( $return, $cardnumber, $cas_ticket );
1470
1506
1471
        # Proxy CAS auth
1507
        # Proxy CAS auth
1472
        if ( $cas && $query->param('PT') ) {
1508
        if ( $cas && $query->param('PT') ) {
Lines 1475-1481 sub check_api_auth { Link Here
1475
1511
1476
            # In case of a CAS authentication, we use the ticket instead of the password
1512
            # In case of a CAS authentication, we use the ticket instead of the password
1477
            my $PT = $query->param('PT');
1513
            my $PT = $query->param('PT');
1478
            ( $return, $cardnumber, $userid ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1514
            ( $return, $cardnumber, $userid, $cas_ticket ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1479
        } else {
1515
        } else {
1480
1516
1481
            # User / password auth
1517
            # User / password auth
Lines 1484-1490 sub check_api_auth { Link Here
1484
                # caller did something wrong, fail the authenticateion
1520
                # caller did something wrong, fail the authenticateion
1485
                return ( "failed", undef, undef );
1521
                return ( "failed", undef, undef );
1486
            }
1522
            }
1487
            ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query );
1523
            my $newuserid;
1524
            ( $return, $cardnumber, $newuserid, $cas_ticket ) = checkpw( $dbh, $userid, $password, $query );
1488
        }
1525
        }
1489
1526
1490
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
1527
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
Lines 1582-1587 sub check_api_auth { Link Here
1582
                $session->param( 'ip',           $session->remote_addr() );
1619
                $session->param( 'ip',           $session->remote_addr() );
1583
                $session->param( 'lasttime',     time() );
1620
                $session->param( 'lasttime',     time() );
1584
            }
1621
            }
1622
            $session->param( 'cas_ticket', $cas_ticket);
1585
            C4::Context->set_userenv(
1623
            C4::Context->set_userenv(
1586
                $session->param('number'),       $session->param('id'),
1624
                $session->param('number'),       $session->param('id'),
1587
                $session->param('cardnumber'),   $session->param('firstname'),
1625
                $session->param('cardnumber'),   $session->param('firstname'),
Lines 1788-1796 sub checkpw { Link Here
1788
        # In case of a CAS authentication, we use the ticket instead of the password
1826
        # In case of a CAS authentication, we use the ticket instead of the password
1789
        my $ticket = $query->param('ticket');
1827
        my $ticket = $query->param('ticket');
1790
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1828
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1791
        my ( $retval, $retcard, $retuserid ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1829
        my ( $retval, $retcard, $retuserid, $cas_ticket ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1792
        if ( $retval ) {
1830
        if ( $retval ) {
1793
            @return = ( $retval, $retcard, $retuserid );
1831
            @return = ( $retval, $retcard, $retuserid, $cas_ticket );
1832
        } else {
1833
            @return = (0);
1794
        }
1834
        }
1795
        $passwd_ok = $retval;
1835
        $passwd_ok = $retval;
1796
    }
1836
    }
(-)a/C4/Auth_with_cas.pm (-4 / +8 lines)
Lines 104-121 sub checkpw_cas { Link Here
104
            my $userid = $val->user();
104
            my $userid = $val->user();
105
            $debug and warn "User CAS authenticated as: $userid";
105
            $debug and warn "User CAS authenticated as: $userid";
106
106
107
            # 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
108
            
107
            # Does it match one of our users ?
109
            # Does it match one of our users ?
108
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
110
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
109
            $sth->execute($userid);
111
            $sth->execute($userid);
110
            if ( $sth->rows ) {
112
            if ( $sth->rows ) {
111
                $retnumber = $sth->fetchrow;
113
                $retnumber = $sth->fetchrow;
112
                return ( 1, $retnumber, $userid );
114
                return ( 1, $retnumber, $userid, $ticket );
113
            }
115
            }
114
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
116
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
115
            $sth->execute($userid);
117
            $sth->execute($userid);
116
            if ( $sth->rows ) {
118
            if ( $sth->rows ) {
117
                $retnumber = $sth->fetchrow;
119
                $retnumber = $sth->fetchrow;
118
                return ( 1, $retnumber, $userid );
120
                return ( 1, $retnumber, $userid, $ticket );
119
            }
121
            }
120
122
121
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
123
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
Lines 153-171 sub check_api_auth_cas { Link Here
153
155
154
            my $userid = $r->user;
156
            my $userid = $r->user;
155
157
158
            # 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
159
156
            # Does it match one of our users ?
160
            # Does it match one of our users ?
157
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
161
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
158
            $sth->execute($userid);
162
            $sth->execute($userid);
159
            if ( $sth->rows ) {
163
            if ( $sth->rows ) {
160
                $retnumber = $sth->fetchrow;
164
                $retnumber = $sth->fetchrow;
161
                return ( 1, $retnumber, $userid );
165
                return ( 1, $retnumber, $userid, $PT );
162
            }
166
            }
163
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
167
            $sth = $dbh->prepare("select userid from borrowers where cardnumber=?");
164
            return $r->user;
168
            return $r->user;
165
            $sth->execute($userid);
169
            $sth->execute($userid);
166
            if ( $sth->rows ) {
170
            if ( $sth->rows ) {
167
                $retnumber = $sth->fetchrow;
171
                $retnumber = $sth->fetchrow;
168
                return ( 1, $retnumber, $userid );
172
                return ( 1, $retnumber, $userid, $PT );
169
            }
173
            }
170
174
171
            # If we reach this point, then the user is a valid CAS user, but not a Koha user
175
            # 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 60-65 BEGIN { Link Here
60
        import C4::External::BakerTaylor qw(&image_url &link_url);
60
        import C4::External::BakerTaylor qw(&image_url &link_url);
61
    }
61
    }
62
}
62
}
63
my $logout='';
64
# CAS Single Sign Out
65
if (C4::Context->preference('casAuthentication')){
66
    # Check we havent been hit by a logout call
67
    my $xml = $query->param('logoutRequest');
68
    if ($xml) {
69
        my $dom = XML::LibXML->load_xml(string => $xml);
70
        my $ticket;
71
        foreach my $node ($dom->findnodes('/samlp:LogoutRequest')){
72
            $ticket = $node->findvalue('./samlp:SessionIndex');
73
        }
74
        $query->param(-name =>'logout.x', -value => 1);
75
        $query->param(-name =>'cas_ticket', -value => $ticket);
76
        $logout=1;
77
    }
78
}
63
79
64
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
80
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
65
    {
81
    {
Lines 71-76 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
71
    }
87
    }
72
);
88
);
73
89
90
if ($logout){
91
    print $query->header;
92
    exit;
93
}
94
95
74
my %renewed = map { $_ => 1 } split( ':', $query->param('renewed') );
96
my %renewed = map { $_ => 1 } split( ':', $query->param('renewed') );
75
97
76
my $show_priority;
98
my $show_priority;
77
- 

Return to bug 19160