diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fa67df..24c08e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `OpenIdLoginAuthenticator::onAuthenticationFailure()` now chains the + original exception via `previous` and includes its message, so logs and + error reporters retain the cause (timeout vs. signature mismatch vs. + wrong nonce). Symfony's security component still renders only the safe + message key to the user. - Strengthened tests guided by mutation testing; mutation score raised to 100% with a CI threshold of 95 (`minCoveredMsi` in `infection.json5`) - Test fixtures use RFC 2606 reserved domains (`provider.example.org`, diff --git a/src/Security/OpenIdLoginAuthenticator.php b/src/Security/OpenIdLoginAuthenticator.php index 440e38e..e207408 100644 --- a/src/Security/OpenIdLoginAuthenticator.php +++ b/src/Security/OpenIdLoginAuthenticator.php @@ -78,6 +78,9 @@ protected function validateClaims(Request $request): array public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response { - throw new AuthenticationException('Error occurred validating openid login'); + // Preserve the cause so logs and error reporters can see what actually + // failed (timeout, signature mismatch, wrong nonce, etc.). Symfony's + // security component renders only the safe message key to the user. + throw new AuthenticationException(sprintf('Error occurred validating openid login: %s', $exception->getMessage()), $exception->getCode(), $exception); } } diff --git a/tests/Security/OpenIdLoginAuthenticatorTest.php b/tests/Security/OpenIdLoginAuthenticatorTest.php index e2704cf..96f371c 100644 --- a/tests/Security/OpenIdLoginAuthenticatorTest.php +++ b/tests/Security/OpenIdLoginAuthenticatorTest.php @@ -40,13 +40,17 @@ public function testSupports(): void $this->assertTrue($this->authenticator->supports($request)); } - public function testOnAuthenticationFailure(): void + public function testOnAuthenticationFailurePreservesCause(): void { - $this->expectException(AuthenticationException::class); + $cause = new AuthenticationException('Original cause message'); - $exception = new AuthenticationException(); - - $this->authenticator->onAuthenticationFailure(new Request(), $exception); + try { + $this->authenticator->onAuthenticationFailure(new Request(), $cause); + $this->fail('Expected AuthenticationException'); + } catch (AuthenticationException $thrown) { + $this->assertSame($cause, $thrown->getPrevious(), 'Original exception must be chained as previous'); + $this->assertStringContainsString('Original cause message', $thrown->getMessage(), 'Cause message must be preserved for logs'); + } } public function testValidateClaimsWrongState(): void