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

(-)a/Koha/Auth/Identity/Referer.pm (+121 lines)
Line 0 Link Here
1
package Koha::Auth::Identity::Referer;
2
3
#
4
# This file is part of Koha.
5
#
6
# Koha is free software; you can redistribute it and/or modify it
7
# under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# Koha is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with Koha; if not, see <https://www.gnu.org/licenses>.
18
19
use Modern::Perl;
20
21
use C4::Context;
22
23
=head1 NAME
24
25
Koha::Auth::Identity::Referer
26
27
=head1 SYNOPSIS
28
29
    use Koha::Auth::Identity::Referer;
30
31
    Koha::Auth::Identity::Referer->store_referer({
32
        referer => $c->req->headers->referer,
33
        interface => $interface,
34
        session => $session,
35
    });
36
37
    my $target_uri = Koha::Auth::Identity::Referer->get_referer({
38
        session => $session,
39
    });
40
41
=head1 DESCRIPTION
42
43
    Class for working with HTTP referrers specifically for
44
    when doing SSO.
45
46
=head1 FUNCTIONS
47
48
=head2 store_referer
49
50
    Koha::Auth::Identity::Referer->store_referer({
51
        referer => $c->req->headers->referer,
52
        interface => $interface,
53
        session => $session,
54
    });
55
56
    If the referer is for a Koha URL, then it gets saved
57
    in a session variable for use after a successful SSO login.
58
59
=cut
60
61
sub store_referer {
62
    my ( $class, $args ) = @_;
63
    my $referer   = $args->{referer};
64
    my $interface = $args->{interface};
65
    my $session   = $args->{session};
66
    my $valid_referer;
67
    if ( $referer && $interface && $session ) {
68
        my $base_url;
69
        if ( $interface eq 'opac' ) {
70
            $base_url = C4::Context->preference('OPACBaseURL');
71
        } else {
72
            $base_url = C4::Context->preference('staffClientBaseURL');
73
        }
74
        if ( $base_url && $referer && $referer =~ /^\Q$base_url\E/ ) {
75
            my $referer_uri = URI->new($referer);
76
77
            #NOTE: Remove logout.x query param to prevent logout loops
78
            $referer_uri->query_param_delete('logout.x') if $referer_uri->query_param('logout.x');
79
            my $referer_to_save = $referer_uri->path_query();
80
            if ($referer_to_save) {
81
82
                #NOTE: Don't bother saving a root referer
83
                #NOTE: Don't save opac-main.pl because it should redirect to opac-user.pl
84
                unless ( ( $referer_to_save eq '/' ) || ( $referer_to_save eq '/cgi-bin/koha/opac-main.pl' ) ) {
85
                    $session->param( 'idp_referer', $referer_to_save );
86
                    $session->flush();
87
                }
88
            }
89
        }
90
    }
91
    return $valid_referer;
92
}
93
94
=head2 get_referer
95
96
    my $target_uri = Koha::Auth::Identity::Referer->get_referer({
97
        session => $session,
98
    });
99
100
    If a referer was stored in a session variable, then we retrieve
101
    it for use by SSO functionality. That is, after a successful SSO, we'll
102
    redirect to this referer, so we wind up back where we started.
103
104
=cut
105
106
sub get_referer {
107
    my ( $class, $args ) = @_;
108
    my $referer;
109
    my $session = $args->{session};
110
    if ($session) {
111
        my $idp_referer = $session->param('idp_referer');
112
        if ($idp_referer) {
113
            $referer = $idp_referer;
114
            $session->clear('idp_referer');
115
            $session->flush();
116
        }
117
    }
118
    return $referer;
119
}
120
121
1;
(-)a/Koha/REST/V1/OAuth/Client.pm (+25 lines)
Lines 25-30 use Scalar::Util qw(blessed); Link Here
25
use Try::Tiny;
25
use Try::Tiny;
26
use Koha::Token;
26
use Koha::Token;
27
use URI::Escape qw(uri_escape_utf8);
27
use URI::Escape qw(uri_escape_utf8);
28
use Koha::Session;
29
use Koha::Auth::Identity::Referer;
28
30
29
=head1 NAME
31
=head1 NAME
30
32
Lines 63-68 sub login { Link Here
63
        $uri          = '/cgi-bin/koha/mainpage.pl';
65
        $uri          = '/cgi-bin/koha/mainpage.pl';
64
    }
66
    }
65
67
68
    my $current_session;
69
    my $current_session_cookie = $c->req->cookie('CGISESSID');
70
    if ($current_session_cookie) {
71
        my $current_session_id = $current_session_cookie->value;
72
        $current_session = Koha::Session->get_session( { sessionID => $current_session_id } );
73
    }
74
66
    unless ( $provider_config && $provider_config->{authorize_url} ) {
75
    unless ( $provider_config && $provider_config->{authorize_url} ) {
67
        my $error = "No configuration found for your provider";
76
        my $error = "No configuration found for your provider";
68
        return $c->redirect_to( $uri . "?auth_error=$error" );
77
        return $c->redirect_to( $uri . "?auth_error=$error" );
Lines 98-103 sub login { Link Here
98
107
99
        # initial request, generate CSRF token
108
        # initial request, generate CSRF token
100
        $state = Koha::Token->new->generate_csrf( { session_id => $c->req->cookie('CGISESSID')->value } );
109
        $state = Koha::Token->new->generate_csrf( { session_id => $c->req->cookie('CGISESSID')->value } );
110
111
        Koha::Auth::Identity::Referer->store_referer(
112
            {
113
                referer   => $c->req->headers->referer,
114
                interface => $interface,
115
                session   => $current_session,
116
            }
117
        );
101
    }
118
    }
102
119
103
    return $c->oauth2->get_token_p(
120
    return $c->oauth2->get_token_p(
Lines 133-138 sub login { Link Here
133
150
134
                $c->cookie( CGISESSID => $session_id, { path => "/" } );
151
                $c->cookie( CGISESSID => $session_id, { path => "/" } );
135
152
153
                my $target_uri = Koha::Auth::Identity::Referer->get_referer(
154
                    {
155
                        session => $current_session,
156
                    }
157
                );
158
                if ($target_uri) {
159
                    $uri = $target_uri;
160
                }
136
                $c->redirect_to($uri);
161
                $c->redirect_to($uri);
137
            } catch {
162
            } catch {
138
                my $error = $_;
163
                my $error = $_;
(-)a/t/Koha/Auth/Identity/Referer.t (-1 / +234 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::NoWarnings;
21
use Test::More tests => 10;
22
use t::lib::Mocks;
23
24
use C4::Auth qw();
25
26
use_ok('Koha::Auth::Identity::Referer');
27
28
subtest 'Typical staff success' => sub {
29
    plan tests => 1;
30
    my $session = C4::Auth::get_session("");
31
32
    t::lib::Mocks::mock_preference( 'staffClientBaseURL', 'http://mystaffadmin' );
33
34
    Koha::Auth::Identity::Referer->store_referer(
35
        {
36
            referer   => 'http://mystaffadmin/cgi-bin/koha/catalogue/search.pl?q=test',
37
            interface => 'staff',
38
            session   => $session,
39
        }
40
    );
41
42
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
43
        {
44
            session => $session,
45
        }
46
    );
47
48
    is( $target_uri, '/cgi-bin/koha/catalogue/search.pl?q=test', 'Correct staff referer processed' );
49
50
    $session->delete;
51
    $session->flush;
52
};
53
54
subtest 'External staff referrers do not get saved' => sub {
55
    plan tests => 1;
56
    my $session = C4::Auth::get_session("");
57
58
    t::lib::Mocks::mock_preference( 'staffClientBaseURL', 'http://mystaffadmin' );
59
60
    Koha::Auth::Identity::Referer->store_referer(
61
        {
62
            referer   => 'http://externalreferer',
63
            interface => 'staff',
64
            session   => $session,
65
        }
66
    );
67
68
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
69
        {
70
            session => $session,
71
        }
72
    );
73
74
    is( $target_uri, undef, 'Bad referrers do not get stored' );
75
76
    $session->delete;
77
    $session->flush;
78
};
79
80
subtest 'Staff logout referer does not lead to loop' => sub {
81
    plan tests => 1;
82
    my $session = C4::Auth::get_session("");
83
84
    t::lib::Mocks::mock_preference( 'staffClientBaseURL', 'http://mystaffadmin' );
85
86
    Koha::Auth::Identity::Referer->store_referer(
87
        {
88
            referer   => 'http://mystaffadmin/cgi-bin/koha/mainpage.pl?logout.x=1',
89
            interface => 'staff',
90
            session   => $session,
91
        }
92
    );
93
94
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
95
        {
96
            session => $session,
97
        }
98
    );
99
100
    is( $target_uri, '/cgi-bin/koha/mainpage.pl', 'Staff logout URL does not lead to loop' );
101
102
    $session->delete;
103
    $session->flush;
104
};
105
106
subtest 'Typical OPAC success' => sub {
107
    plan tests => 1;
108
    my $session = C4::Auth::get_session("");
109
110
    t::lib::Mocks::mock_preference( 'OPACBaseURL', 'http://myopac' );
111
112
    Koha::Auth::Identity::Referer->store_referer(
113
        {
114
            referer   => 'http://myopac/cgi-bin/koha/opac-detail.pl?biblionumber=999',
115
            interface => 'opac',
116
            session   => $session,
117
        }
118
    );
119
120
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
121
        {
122
            session => $session,
123
        }
124
    );
125
126
    is( $target_uri, '/cgi-bin/koha/opac-detail.pl?biblionumber=999', 'Correct OPAC referer processed' );
127
128
    $session->delete;
129
    $session->flush;
130
};
131
132
subtest 'OPAC logout referer does not lead to loop' => sub {
133
    plan tests => 1;
134
    my $session = C4::Auth::get_session("");
135
136
    t::lib::Mocks::mock_preference( 'OPACBaseURL', 'http://myopac' );
137
138
    Koha::Auth::Identity::Referer->store_referer(
139
        {
140
            referer   => 'http://myopac/cgi-bin/koha/opac-main.pl?logout.x=1',
141
            interface => 'opac',
142
            session   => $session,
143
        }
144
    );
145
146
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
147
        {
148
            session => $session,
149
        }
150
    );
151
152
    is( $target_uri, undef, 'OPAC logout URL does not lead to loop' );
153
154
    $session->delete;
155
    $session->flush;
156
};
157
158
subtest 'Do not save referer to OPAC root' => sub {
159
    plan tests => 1;
160
    my $session = C4::Auth::get_session("");
161
162
    t::lib::Mocks::mock_preference( 'OPACBaseURL', 'http://myopac' );
163
164
    Koha::Auth::Identity::Referer->store_referer(
165
        {
166
            referer   => 'http://myopac',
167
            interface => 'opac',
168
            session   => $session,
169
        }
170
    );
171
172
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
173
        {
174
            session => $session,
175
        }
176
    );
177
178
    is( $target_uri, undef, 'Do not save referer to OPAC root' );
179
180
    $session->delete;
181
    $session->flush;
182
};
183
184
subtest 'Do not save referer to OPAC root (ie opac-main.pl)' => sub {
185
    plan tests => 1;
186
    my $session = C4::Auth::get_session("");
187
188
    t::lib::Mocks::mock_preference( 'OPACBaseURL', 'http://myopac' );
189
190
    Koha::Auth::Identity::Referer->store_referer(
191
        {
192
            referer   => 'http://myopac/cgi-bin/koha/opac-main.pl',
193
            interface => 'opac',
194
            session   => $session,
195
        }
196
    );
197
198
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
199
        {
200
            session => $session,
201
        }
202
    );
203
204
    is( $target_uri, undef, 'Do not save referer to OPAC root (ie opac-main.pl)' );
205
206
    $session->delete;
207
    $session->flush;
208
};
209
210
subtest 'External OPAC referrers do not get saved' => sub {
211
    plan tests => 1;
212
    my $session = C4::Auth::get_session("");
213
214
    t::lib::Mocks::mock_preference( 'OPACBaseURL', 'http://myopac' );
215
216
    Koha::Auth::Identity::Referer->store_referer(
217
        {
218
            referer   => 'http://externalreferer',
219
            interface => 'opac',
220
            session   => $session,
221
        }
222
    );
223
224
    my $target_uri = Koha::Auth::Identity::Referer->get_referer(
225
        {
226
            session => $session,
227
        }
228
    );
229
230
    is( $target_uri, undef, 'Bad referrers do not get stored' );
231
232
    $session->delete;
233
    $session->flush;
234
};

Return to bug 34164