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

(-)a/t/db_dependent/Koha/Auth/Client/OAuth.t (-1 / +257 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2025 Koha Development Team
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 4;
23
use Test::MockModule;
24
use Test::NoWarnings;
25
26
use JSON         qw(encode_json);
27
use MIME::Base64 qw(encode_base64url);
28
29
use Koha::Auth::Client::OAuth;
30
use Koha::Database;
31
32
use t::lib::TestBuilder;
33
34
my $schema  = Koha::Database->new->schema;
35
my $builder = t::lib::TestBuilder->new;
36
37
subtest '_get_data_and_patron() with id_token tests' => sub {
38
    plan tests => 4;
39
40
    $schema->storage->txn_begin;
41
42
    my $client = Koha::Auth::Client::OAuth->new;
43
44
    # Create test patron
45
    my $patron = $builder->build_object(
46
        {
47
            class => 'Koha::Patrons',
48
            value => { email => 'test@example.com' }
49
        }
50
    );
51
52
    # Create provider with email matchpoint
53
    my $provider = $builder->build_object(
54
        {
55
            class => 'Koha::Auth::Identity::Providers',
56
            value => {
57
                matchpoint => 'email',
58
                mapping    => encode_json(
59
                    {
60
                        email     => 'mail',
61
                        firstname => 'given_name',
62
                        surname   => 'family_name'
63
                    }
64
                )
65
            }
66
        }
67
    );
68
69
    # Create JWT token with user data
70
    my $claims = {
71
        mail        => 'test@example.com',
72
        given_name  => 'John',
73
        family_name => 'Doe'
74
    };
75
76
    my $id_token = 'header.' . encode_base64url( encode_json($claims) ) . '.signature';
77
78
    my $data   = { id_token => $id_token };
79
    my $config = {};
80
81
    # Test the method
82
    my ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
83
        {
84
            provider => $provider,
85
            data     => $data,
86
            config   => $config
87
        }
88
    );
89
90
    # Verify results
91
    is( $mapped_data->{email},     'test@example.com', 'Email mapped correctly' );
92
    is( $mapped_data->{firstname}, 'John',             'First name mapped correctly' );
93
    is( $mapped_data->{surname},   'Doe',              'Surname mapped correctly' );
94
    is( $found_patron->id,         $patron->id,        'Patron found by email matchpoint' );
95
96
    $schema->storage->txn_rollback;
97
};
98
99
subtest '_get_data_and_patron() with userinfo_url tests' => sub {
100
    plan tests => 5;
101
102
    $schema->storage->txn_begin;
103
104
    my $client = Koha::Auth::Client::OAuth->new;
105
106
    # Create test patron
107
    my $patron = $builder->build_object(
108
        {
109
            class => 'Koha::Patrons',
110
            value => { email => 'userinfo@example.com' }
111
        }
112
    );
113
114
    # Create provider with email matchpoint
115
    my $provider = $builder->build_object(
116
        {
117
            class => 'Koha::Auth::Identity::Providers',
118
            value => {
119
                matchpoint => 'email',
120
                mapping    => encode_json(
121
                    {
122
                        email     => 'email',
123
                        firstname => 'first_name'
124
                    }
125
                )
126
            }
127
        }
128
    );
129
130
    # Mock UserAgent for userinfo endpoint
131
    my $ua_mock      = Test::MockModule->new('Mojo::UserAgent');
132
    my $tx_mock      = Test::MockModule->new('Mojo::Transaction::HTTP');
133
    my $res_mock     = Test::MockModule->new('Mojo::Message::Response');
134
    my $headers_mock = Test::MockModule->new('Mojo::Headers');
135
136
    $headers_mock->mock( 'content_type', sub { 'application/json' } );
137
    $res_mock->mock( 'code', sub { '200' } );
138
    $res_mock->mock(
139
        'json',
140
        sub {
141
            return {
142
                email      => 'userinfo@example.com',
143
                first_name => 'Jane'
144
            };
145
        }
146
    );
147
    $res_mock->mock(
148
        'headers',
149
        sub {
150
            my $headers = {};
151
            bless $headers, 'Mojo::Headers';
152
            return $headers;
153
        }
154
    );
155
156
    $tx_mock->mock(
157
        'res',
158
        sub {
159
            my $res = {};
160
            bless $res, 'Mojo::Message::Response';
161
            return $res;
162
        }
163
    );
164
165
    $ua_mock->mock(
166
        'get',
167
        sub {
168
            my $tx = {};
169
            bless $tx, 'Mojo::Transaction::HTTP';
170
            return $tx;
171
        }
172
    );
173
174
    my $data   = { access_token => 'test_token' };
175
    my $config = { userinfo_url => 'https://provider.com/userinfo' };
176
177
    # Test the method
178
    my ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
179
        {
180
            provider => $provider,
181
            data     => $data,
182
            config   => $config
183
        }
184
    );
185
186
    # Verify results
187
    is( $mapped_data->{email},     'userinfo@example.com', 'Email mapped from userinfo' );
188
    is( $mapped_data->{firstname}, 'Jane',                 'First name mapped from userinfo' );
189
    is( $found_patron->id,         $patron->id,            'Patron found by email from userinfo' );
190
191
    # Test with both id_token and userinfo (patron should be found from id_token first)
192
    my $id_token_claims = { email => 'token@example.com' };
193
    my $id_token        = 'header.' . encode_base64url( encode_json($id_token_claims) ) . '.signature';
194
195
    my $token_patron = $builder->build_object(
196
        {
197
            class => 'Koha::Patrons',
198
            value => { email => 'token@example.com' }
199
        }
200
    );
201
202
    $data->{id_token} = $id_token;
203
204
    ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
205
        {
206
            provider => $provider,
207
            data     => $data,
208
            config   => $config
209
        }
210
    );
211
212
    is( $found_patron->id,     $token_patron->id,      'Patron found from id_token takes precedence' );
213
    is( $mapped_data->{email}, 'userinfo@example.com', 'But userinfo data still merged' );
214
215
    $schema->storage->txn_rollback;
216
};
217
218
subtest '_get_data_and_patron() no patron found tests' => sub {
219
    plan tests => 2;
220
221
    $schema->storage->txn_begin;
222
223
    my $client = Koha::Auth::Client::OAuth->new;
224
225
    # Create provider
226
    my $provider = $builder->build_object(
227
        {
228
            class => 'Koha::Auth::Identity::Providers',
229
            value => {
230
                matchpoint => 'email',
231
                mapping    => encode_json( { email => 'mail' } )
232
            }
233
        }
234
    );
235
236
    # Create token for non-existent user
237
    my $claims   = { mail => 'nonexistent@example.com' };
238
    my $id_token = 'header.' . encode_base64url( encode_json($claims) ) . '.signature';
239
240
    my $data   = { id_token => $id_token };
241
    my $config = {};
242
243
    # Test the method
244
    my ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
245
        {
246
            provider => $provider,
247
            data     => $data,
248
            config   => $config
249
        }
250
    );
251
252
    # Verify results
253
    is( $mapped_data->{email}, 'nonexistent@example.com', 'Email mapped correctly' );
254
    is( $found_patron,         undef,                     'No patron found for non-existent email' );
255
256
    $schema->storage->txn_rollback;
257
};

Return to bug 33782