From 0d7e4e7628417545222b51cc0db3d39660ebb693 Mon Sep 17 00:00:00 2001 From: Hani Kh Date: Thu, 26 Dec 2024 23:08:43 +0800 Subject: [PATCH 1/2] add support for reject_login_request --- Changes | 2 ++ lib/WebService/Hydra/Client.pm | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Changes b/Changes index e13c1b1..7025249 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,7 @@ {{$NEXT}} +- Added reject_login_request method + 0.004 2024-12-03 10:30:12+00:00 UTC - Added timeout to `HTTP::Tiny` diff --git a/lib/WebService/Hydra/Client.pm b/lib/WebService/Hydra/Client.pm index ba7aa3b..a0ed11f 100644 --- a/lib/WebService/Hydra/Client.pm +++ b/lib/WebService/Hydra/Client.pm @@ -227,6 +227,41 @@ method accept_login_request ($login_challenge, $accept_payload) { return $result->{data}; } +=head2 reject_login_request + +Rejects the login request and returns the response from hydra. + +Arguments: + +=over 1 + +=item C<$login_challenge> + +Authentication challenge string that is used to identify the login request. + +=item C<$reject_payload> + +Payload to be sent to the Hydra service to reject the login request. + +=back + +=cut + +method reject_login_request ($login_challenge, $reject_payload) { + my $method = "PUT"; + my $path = "$admin_endpoint/admin/oauth2/auth/requests/login/reject?challenge=$login_challenge"; + + my $result = $self->api_call($method, $path, $reject_payload); + if ($result->{code} != OK_STATUS_CODE) { + WebService::Hydra::Exception::InvalidLoginRequest->new( + message => "Failed to reject login request", + category => "client", + details => $result + )->throw; + } + return $result->{data}; +} + =head2 get_logout_request Get the logout request and return the response from Hydra. From 636dfa4f81140305951c4589695172e80c540991 Mon Sep 17 00:00:00 2001 From: Hani Kh Date: Thu, 26 Dec 2024 23:18:08 +0800 Subject: [PATCH 2/2] add test --- t/unit/hydra_client.t | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/t/unit/hydra_client.t b/t/unit/hydra_client.t index a1793c9..012e109 100644 --- a/t/unit/hydra_client.t +++ b/t/unit/hydra_client.t @@ -539,6 +539,75 @@ subtest 'oidc_config' => sub { }; +subtest 'reject_login_request' => sub { + my $mock_hydra = Test::MockModule->new('WebService::Hydra::Client'); + my $mock_api_response; + my @params; + $mock_hydra->redefine( + 'api_call', + sub { + (@params) = @_; + return $mock_api_response; + }); + + my $client = WebService::Hydra::Client->new( + admin_endpoint => 'http://dummyhydra.com/admin', + public_endpoint => 'http://dummyhydra.com' + ); + + my $reject_payload = { + error => 'access_denied', + error_debug => 'User authentication failed', + error_description => 'Invalid credentials provided', + error_hint => 'Check your username and password', + status_code => 401 + }; + + # Test for 200 OK status code + $mock_api_response = { + code => 200, + data => {redirect_to => 'http://dummyhydra.com/error'} + }; + + my $got = $client->reject_login_request("VALID_CHALLENGE", $reject_payload); + is $params[1], 'PUT', 'PUT request method'; + is $params[2], 'http://dummyhydra.com/admin/admin/oauth2/auth/requests/login/reject?challenge=VALID_CHALLENGE', + 'Request URL built with correct parameters'; + is_deeply $params[3], $reject_payload, 'Request payload is correct'; + is_deeply $got, $mock_api_response->{data}, 'api_call response correctly parsed'; + + # Test for non-200 status codes + $mock_api_response = { + code => 400, + data => { + error => "string", + error_description => "string", + status_code => 400 + } + }; + + dies_ok { $client->reject_login_request("INVALID_CHALLENGE", $reject_payload) } + 'Dies if non-200 status code is received from api_call'; + + my $exception = $@; + my $expected_exception = WebService::Hydra::Exception::InvalidLoginRequest->new( + message => 'Failed to reject login request', + category => 'client', + details => $mock_api_response + ); + is_deeply $exception, $expected_exception, 'Return api_call response for Non 200 status code'; + + # Test network failure + $mock_hydra->redefine( + 'api_call', + sub { + die "Request to http://dummyhydra.com/admin/oauth2/auth/requests/login/reject?challenge=VALID_CHALLENGE failed - Network issue"; + }); + + dies_ok { $client->reject_login_request("VALID_CHALLENGE", $reject_payload) } + 'Dies if http request fails for some reason'; +}; + subtest 'validate_token' => sub { my $mock_hydra = Test::MockModule->new('WebService::Hydra::Client'); my $mock_token = 'mock.jwt.token';