Bug 43375: Regression tests

This patch adds a regression test demonstrating that the OAuth
userinfo_url response parsing fails when the Content-Type header
contains extra parameters beyond charset (e.g. Microsoft Graph API
returns application/json;odata.metadata=minimal;odata.streaming=true).

The strict regex in _get_data_and_patron only matches Content-Type
values with an optional ;charset=... suffix, causing valid JSON
responses to be silently misinterpreted as URL-encoded form data.

Test plan:
1. Apply this patch
2. Run:
   $ ktd --shell
  k$ prove t/db_dependent/Koha/Auth/Client/OAuth.t
=> FAIL: New subtest fails - email is undef, patron not found
3. Sign off :-D

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Tomás Cohen Arazi 2026-08-24 14:57:08 -03:00 committed by Pedro Amorim
parent 6975b6616b
commit 63ffc0b28f
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
1 changed files with 102 additions and 2 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/perl
#!/usr/bin/env perl
# Copyright 2025 Koha Development Team
#
@ -19,7 +19,7 @@
use Modern::Perl;
use Test::More tests => 4;
use Test::More tests => 5;
use Test::MockModule;
use Test::NoWarnings;
@ -255,3 +255,103 @@ subtest '_get_data_and_patron() no patron found tests' => sub {
$schema->storage->txn_rollback;
};
subtest '_get_data_and_patron() userinfo_url with extra Content-Type params (bug 43375)' => sub {
plan tests => 2;
$schema->storage->txn_begin;
my $client = Koha::Auth::Client::OAuth->new;
# Create test patron
my $patron = $builder->build_object(
{
class => 'Koha::Patrons',
value => { email => 'graph@example.com' }
}
);
# Create provider with email matchpoint
my $provider = $builder->build_object(
{
class => 'Koha::Auth::Identity::Providers',
value => {
matchpoint => 'email',
mapping => encode_json(
{
email => 'mail',
firstname => 'givenName',
surname => 'surname',
}
)
}
}
);
# Mock UserAgent - simulate Microsoft Graph API response
# Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
my $ua_mock = Test::MockModule->new('Mojo::UserAgent');
my $tx_mock = Test::MockModule->new('Mojo::Transaction::HTTP');
my $res_mock = Test::MockModule->new('Mojo::Message::Response');
my $headers_mock = Test::MockModule->new('Mojo::Headers');
$headers_mock->mock(
'content_type',
sub {
'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8';
}
);
$res_mock->mock( 'code', sub { '200' } );
$res_mock->mock(
'json',
sub {
return {
mail => 'graph@example.com',
givenName => 'Azure',
surname => 'User',
};
}
);
$res_mock->mock(
'headers',
sub {
my $headers = {};
bless $headers, 'Mojo::Headers';
return $headers;
}
);
$tx_mock->mock(
'res',
sub {
my $res = {};
bless $res, 'Mojo::Message::Response';
return $res;
}
);
$ua_mock->mock(
'get',
sub {
my $tx = {};
bless $tx, 'Mojo::Transaction::HTTP';
return $tx;
}
);
my $data = { access_token => 'ms_graph_token' };
my $config = { userinfo_url => 'https://graph.microsoft.com/v1.0/me' };
my ( $mapped_data, $found_patron ) = $client->_get_data_and_patron(
{
provider => $provider,
data => $data,
config => $config
}
);
is( $mapped_data->{email}, 'graph@example.com', 'Email mapped from MS Graph response with OData Content-Type' );
is( $found_patron->id, $patron->id, 'Patron found despite extra Content-Type parameters' );
$schema->storage->txn_rollback;
};