Skip to content

Commit 43e5db3

Browse files
committed
Refactor error handling for token endpoint
1 parent 477e9bf commit 43e5db3

File tree

2 files changed

+92
-7
lines changed

2 files changed

+92
-7
lines changed

src/OpenIDConnectClient.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,10 +400,8 @@ public function authenticate(): bool
400400

401401
// Throw an error if the server returns one
402402
if (isset($token_json->error)) {
403-
if (isset($token_json->error_description)) {
404-
throw new OpenIDConnectClientException($token_json->error_description);
405-
}
406-
throw new OpenIDConnectClientException('Got response: ' . $token_json->error);
403+
$desc = isset($token_json->error_description) ? ' Description: ' . $token_json->error_description : '';
404+
throw new OpenIDConnectClientException('Error: ' . $token_json->error .$desc);
407405
}
408406

409407
if (!property_exists($token_json, 'id_token')) {

tests/OpenIDConnectClientTest.php

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ protected function setUp(): void
4242
}
4343

4444
/**
45-
* @covers Jumbojett\\OpenIDConnectClient::verifyIdTokenClaims
45+
* @covers Jumbojett\OpenIDConnectClient::verifyIdTokenClaims
4646
* @dataProvider provideTestVerifyIdTokenClaimsData
4747
* @return void
4848
*/
@@ -325,9 +325,8 @@ public function provider(): array
325325
}
326326

327327
/**
328-
* @covers Jumbojett\\OpenIDConnectClient::verifyLogoutTokenClaims
328+
* @covers Jumbojett\OpenIDConnectClient::verifyLogoutTokenClaims
329329
* @dataProvider provideTestVerifyLogoutTokenClaimsData
330-
* @throws OpenIDConnectClientException
331330
*/
332331
public function testVerifyLogoutTokenClaims($claims, $expectedResult)
333332
{
@@ -1940,6 +1939,94 @@ public function testAuthenticateAuthorizationCodeFlowWithNoState()
19401939
$client->authenticate();
19411940
}
19421941

1942+
public function testAuthenticateAuthorizationCodeWithError()
1943+
{
1944+
// Generate random values for the ID token
1945+
$code = bin2hex(random_bytes(6));
1946+
$nonce = bin2hex(random_bytes(6));
1947+
$state = bin2hex(random_bytes(6));
1948+
1949+
// Mock the OpenIDConnectClient, only mocking the fetchURL method
1950+
$client = $this->getMockBuilder(OpenIDConnectClient::class)
1951+
->setConstructorArgs([
1952+
'https://example.org',
1953+
'fake-client-id',
1954+
'fake-client-secret',
1955+
])
1956+
->onlyMethods(['fetchURL'])
1957+
->getMock();
1958+
1959+
$client->expects($this->any())
1960+
->method('fetchURL')
1961+
->with($this->anything())
1962+
->will($this->returnCallback(function (string$url, ?string $post_body = null, array $headers = []) use ($code) {
1963+
switch ($url) {
1964+
case 'https://example.org/.well-known/openid-configuration':
1965+
return new Response(200, 'application/json', json_encode([
1966+
'issuer' => 'https://example.org/',
1967+
'authorization_endpoint' => 'https://example.org/authorize',
1968+
'token_endpoint' => 'https://example.org/token',
1969+
'userinfo_endpoint' => 'https://example.org/userinfo',
1970+
'jwks_uri' => 'https://example.org/jwks',
1971+
'response_types_supported' => ['code', 'id_token'],
1972+
'subject_types_supported' => ['public'],
1973+
'id_token_signing_alg_values_supported' => ['RS256'],
1974+
]));
1975+
case 'https://example.org/token':
1976+
return new Response(200, 'application/json', json_encode([
1977+
'error' => 'invalid_request',
1978+
'error_description' => 'Example description'
1979+
]));
1980+
default:
1981+
throw new Exception("Unexpected request: $url");
1982+
}
1983+
}));
1984+
1985+
// Simulate the state and nonce have been set in the session
1986+
$_SESSION['openid_connect_state'] = $state;
1987+
$_SESSION['openid_connect_nonce'] = $nonce;
1988+
1989+
// Simulate incoming request with code and state
1990+
$_REQUEST['code'] = $code;
1991+
$_REQUEST['state'] = $state;
1992+
1993+
// Call the authenticate method, should throw an exception
1994+
$this->expectException(OpenIDConnectClientException::class);
1995+
$this->expectExceptionMessage('Error: invalid_request Description: Example description');
1996+
$client->authenticate();
1997+
}
1998+
1999+
public function testAuthenticateThrowsExceptionOnError()
2000+
{
2001+
$client = new OpenIDConnectClient(
2002+
'https://example.org',
2003+
'fake-client-id',
2004+
'fake-client-secret',
2005+
);
2006+
2007+
$_REQUEST['error'] = 'invalid_request';
2008+
2009+
$this->expectException(OpenIDConnectClientException::class);
2010+
$this->expectExceptionMessage('Error: invalid_request');
2011+
$client->authenticate();
2012+
}
2013+
2014+
public function testAuthenticateThrowsExceptionOnErrorWithDescription()
2015+
{
2016+
$client = new OpenIDConnectClient(
2017+
'https://example.org',
2018+
'fake-client-id',
2019+
'fake-client-secret',
2020+
);
2021+
2022+
$_REQUEST['error'] = 'invalid_request';
2023+
$_REQUEST['error_description'] = 'Unsupported response_type value';
2024+
2025+
$this->expectException(OpenIDConnectClientException::class);
2026+
$this->expectExceptionMessage('Error: invalid_request Description: Unsupported response_type value');
2027+
$client->authenticate();
2028+
}
2029+
19432030
public function testAuthenticateRedirectsToOP()
19442031
{
19452032
// Mock the OpenIDConnectClient, only mocking the fetchURL method

0 commit comments

Comments
 (0)