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

(-)a/C4/Auth.pm (-12 / +52 lines)
Lines 746-752 sub _timeout_syspref { Link Here
746
sub checkauth {
746
sub checkauth {
747
    my $query = shift;
747
    my $query = shift;
748
    $debug and warn "Checking Auth";
748
    $debug and warn "Checking Auth";
749
750
    # $authnotrequired will be set for scripts which will run without authentication
749
    # $authnotrequired will be set for scripts which will run without authentication
751
    my $authnotrequired = shift;
750
    my $authnotrequired = shift;
752
    my $flagsrequired   = shift;
751
    my $flagsrequired   = shift;
Lines 766-772 sub checkauth { Link Here
766
    my $logout = $query->param('logout.x');
765
    my $logout = $query->param('logout.x');
767
766
768
    my $anon_search_history;
767
    my $anon_search_history;
769
768
    my $cas_ticket = '';
770
    # This parameter is the name of the CAS server we want to authenticate against,
769
    # This parameter is the name of the CAS server we want to authenticate against,
771
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
770
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
772
    my $casparam = $query->param('cas');
771
    my $casparam = $query->param('cas');
Lines 904-911 sub checkauth { Link Here
904
            }
903
            }
905
        }
904
        }
906
    }
905
    }
906
    elsif ($logout && $cas) {
907
        # We got a cas single logout request from a cas server;
908
        my $ticket = $query->param('cas_ticket');
909
        # We've been called as part of the single logout destroy the session associated with the cas ticket
910
        my $storage_method = C4::Context->preference('SessionStorage');
911
        my $dsn;
912
        my $dsn_options;
913
        # shift this to a function make get_session use the function too
914
        my $dbh            = C4::Context->dbh;
915
        if ( $storage_method eq 'mysql' ) {
916
            $dsn = "driver:MySQL;serializer:yaml;id:md5";
917
            $dsn_options = { Handle => $dbh };
918
        }
919
        elsif (  $storage_method eq 'Pg' ) {
920
            $dsn = "driver:PostgreSQL;serializer:yaml;id:md5";
921
            $dsn_options = { Handle => $dbh };
922
        }
923
        elsif ( $storage_method eq 'memcached' && Koha::Caches->get_instance->memcached_cache ) {
924
            $dsn = "driver:memcached;serializer:yaml;id:md5";
925
            my $memcached = Koha::Caches->get_instance()->memcached_cache;
926
            $dsn_options =  { Memcached => $memcached };
927
        }
928
        else {
929
            $dsn = "driver:File;serializer:yaml;id:md5";
930
            my $dir = File::Spec->tmpdir;
931
            my $instance = C4::Context->config( 'database' ); #actually for packages not exactly the instance name, but generally safer to leave it as it is
932
            $dsn_options =  { Directory => "$dir/cgisess_$instance" };
933
        }
934
        my $success =  CGI::Session->find( $dsn, sub {delete_cas_session(@_, $ticket)}, $dsn_options );
935
        sub delete_cas_session {
936
            my $session = shift;
937
            my $ticket = shift;
938
            if ($session->param('cas_ticket') && $session->param('cas_ticket') eq $ticket ) {
939
                $session->delete;
940
                $session->flush;
941
            }
942
        }
943
    }
907
    unless ( $userid || $sessionID ) {
944
    unless ( $userid || $sessionID ) {
908
909
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
945
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
910
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
946
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
911
947
Lines 936-942 sub checkauth { Link Here
936
        {
972
        {
937
            my $password    = $query->param('password');
973
            my $password    = $query->param('password');
938
            my $shibSuccess = 0;
974
            my $shibSuccess = 0;
939
940
            my ( $return, $cardnumber );
975
            my ( $return, $cardnumber );
941
976
942
            # If shib is enabled and we have a shib login, does the login match a valid koha user
977
            # If shib is enabled and we have a shib login, does the login match a valid koha user
Lines 954-960 sub checkauth { Link Here
954
            unless ($shibSuccess) {
989
            unless ($shibSuccess) {
955
                if ( $cas && $query->param('ticket') ) {
990
                if ( $cas && $query->param('ticket') ) {
956
                    my $retuserid;
991
                    my $retuserid;
957
                    ( $return, $cardnumber, $retuserid ) =
992
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
958
                      checkpw( $dbh, $userid, $password, $query, $type );
993
                      checkpw( $dbh, $userid, $password, $query, $type );
959
                    $userid = $retuserid;
994
                    $userid = $retuserid;
960
                    $info{'invalidCasLogin'} = 1 unless ($return);
995
                    $info{'invalidCasLogin'} = 1 unless ($return);
Lines 1014-1020 sub checkauth { Link Here
1014
                }
1049
                }
1015
                else {
1050
                else {
1016
                    my $retuserid;
1051
                    my $retuserid;
1017
                    ( $return, $cardnumber, $retuserid ) =
1052
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1018
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1053
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1019
                    $userid = $retuserid if ($retuserid);
1054
                    $userid = $retuserid if ($retuserid);
1020
                    $info{'invalid_username_or_password'} = 1 unless ($return);
1055
                    $info{'invalid_username_or_password'} = 1 unless ($return);
Lines 1140-1145 sub checkauth { Link Here
1140
                    $session->param( 'ip',           $session->remote_addr() );
1175
                    $session->param( 'ip',           $session->remote_addr() );
1141
                    $session->param( 'lasttime',     time() );
1176
                    $session->param( 'lasttime',     time() );
1142
                }
1177
                }
1178
                $session->param('cas_ticket', $cas_ticket) if $cas_ticket;
1143
                C4::Context->set_userenv(
1179
                C4::Context->set_userenv(
1144
                    $session->param('number'),       $session->param('id'),
1180
                    $session->param('number'),       $session->param('id'),
1145
                    $session->param('cardnumber'),   $session->param('firstname'),
1181
                    $session->param('cardnumber'),   $session->param('firstname'),
Lines 1371-1379 Possible return values in C<$status> are: Link Here
1371
=cut
1407
=cut
1372
1408
1373
sub check_api_auth {
1409
sub check_api_auth {
1410
1374
    my $query         = shift;
1411
    my $query         = shift;
1375
    my $flagsrequired = shift;
1412
    my $flagsrequired = shift;
1376
1377
    my $dbh     = C4::Context->dbh;
1413
    my $dbh     = C4::Context->dbh;
1378
    my $timeout = _timeout_syspref();
1414
    my $timeout = _timeout_syspref();
1379
1415
Lines 1467-1473 sub check_api_auth { Link Here
1467
        # new login
1503
        # new login
1468
        my $userid   = $query->param('userid');
1504
        my $userid   = $query->param('userid');
1469
        my $password = $query->param('password');
1505
        my $password = $query->param('password');
1470
        my ( $return, $cardnumber );
1506
        my ( $return, $cardnumber, $cas_ticket );
1471
1507
1472
        # Proxy CAS auth
1508
        # Proxy CAS auth
1473
        if ( $cas && $query->param('PT') ) {
1509
        if ( $cas && $query->param('PT') ) {
Lines 1476-1482 sub check_api_auth { Link Here
1476
1512
1477
            # In case of a CAS authentication, we use the ticket instead of the password
1513
            # In case of a CAS authentication, we use the ticket instead of the password
1478
            my $PT = $query->param('PT');
1514
            my $PT = $query->param('PT');
1479
            ( $return, $cardnumber, $userid ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1515
            ( $return, $cardnumber, $userid, $cas_ticket ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1480
        } else {
1516
        } else {
1481
1517
1482
            # User / password auth
1518
            # User / password auth
Lines 1485-1491 sub check_api_auth { Link Here
1485
                # caller did something wrong, fail the authenticateion
1521
                # caller did something wrong, fail the authenticateion
1486
                return ( "failed", undef, undef );
1522
                return ( "failed", undef, undef );
1487
            }
1523
            }
1488
            ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query );
1524
            my $newuserid;
1525
            ( $return, $cardnumber, $newuserid, $cas_ticket ) = checkpw( $dbh, $userid, $password, $query );
1489
        }
1526
        }
1490
1527
1491
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
1528
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
Lines 1583-1588 sub check_api_auth { Link Here
1583
                $session->param( 'ip',           $session->remote_addr() );
1620
                $session->param( 'ip',           $session->remote_addr() );
1584
                $session->param( 'lasttime',     time() );
1621
                $session->param( 'lasttime',     time() );
1585
            }
1622
            }
1623
            $session->param( 'cas_ticket', $cas_ticket);
1586
            C4::Context->set_userenv(
1624
            C4::Context->set_userenv(
1587
                $session->param('number'),       $session->param('id'),
1625
                $session->param('number'),       $session->param('id'),
1588
                $session->param('cardnumber'),   $session->param('firstname'),
1626
                $session->param('cardnumber'),   $session->param('firstname'),
Lines 1789-1797 sub checkpw { Link Here
1789
        # In case of a CAS authentication, we use the ticket instead of the password
1827
        # In case of a CAS authentication, we use the ticket instead of the password
1790
        my $ticket = $query->param('ticket');
1828
        my $ticket = $query->param('ticket');
1791
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1829
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1792
        my ( $retval, $retcard, $retuserid ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1830
        my ( $retval, $retcard, $retuserid, $cas_ticket ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1793
        if ( $retval ) {
1831
        if ( $retval ) {
1794
            @return = ( $retval, $retcard, $retuserid );
1832
            @return = ( $retval, $retcard, $retuserid, $cas_ticket );
1833
        } else {
1834
            @return = (0);
1795
        }
1835
        }
1796
        $passwd_ok = $retval;
1836
        $passwd_ok = $retval;
1797
    }
1837
    }
(-)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 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