feat: log OIDC failures through a configurable PSR-3 logger - #54
Open
turegjorup wants to merge 1 commit into
Open
feat: log OIDC failures through a configurable PSR-3 logger#54turegjorup wants to merge 1 commit into
turegjorup wants to merge 1 commit into
Conversation
Nothing in the bundle logged anything, so an expired client secret surfaced only as a failed login with no diagnostics. Every failure path now logs its cause: state and nonce mismatches, the token exchange, unknown providers, unreachable providers, and the CLI login token paths. New logging_options config: `logger` selects the logger service (defaults to the application logger) and `level` the PSR-3 level (defaults to error). OpenIdLoginAuthenticator is abstract and subclassed by consumers, so it receives both through registerForAutoconfiguration() rather than constructor arguments that would break existing subclasses.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## fix/cli-authenticator-preserves-cause #54 +/- ##
=========================================================================
Coverage 100.00% 100.00%
- Complexity 62 69 +7
=========================================================================
Files 9 9
Lines 282 344 +62
=========================================================================
+ Hits 282 344 +62
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The bundle logged nothing at all — no
LoggerInterfaceanywhere insrc/. When the Azure client secret behindsites.itkdev.dkexpired, the token exchange failed withinvalid_clientand the only visible symptom was a failed login; nothing recorded why.Every failure path now logs its cause: state mismatch, empty/missing nonce, the token exchange and claims validation, unknown provider, unreachable provider, and the three CLI login token paths.
Logging is configurable via a new
logging_optionsblock:Two design points worth review:
OpenIdLoginAuthenticatorgets its logger viasetLogger(), not the constructor. The class is abstract and subclassed by every consuming application, whose subclasses callparent::__construct($providerManager). A new constructor argument would either break them or silently leave the logger unset for all of them. It implementsLoggerAwareInterface, and the extension appliessetLogger()/setLogLevel()throughregisterForAutoconfiguration(), so consumer subclasses pick up the configuration with no wiring on their side.LoggerAwareTraitis not used. Its$loggerproperty is nullable, which forces a null check at all four call sites and leaves the class with two states where only one is meaningful; PHPStan also cannot narrow a mutable nullable property across methods. Aprivate LoggerInterface $loggerdefaulted toNullLoggergives one code path — and removes fourNullSafeMethodCallmutants that otherwise only existed because of the nullability.Files Changed
src/Security/OpenIdLoginAuthenticator.php- implementLoggerAwareInterfacewith aNullLoggerdefault; addsetLogLevel(); log the four failure paths.onAuthenticationFailure()logsgetPrevious()as the cause, becauseAuthenticatorManager::handleAuthenticationFailure()substitutes a genericBadCredentialsExceptionfor sensitive failures and keeps the real cause chainedsrc/Controller/LoginController.php,src/Security/CliLoginTokenAuthenticator.php- constructor-injected logger and level (container-instantiated, so no BC concern)src/DependencyInjection/Configuration.php-logging_options.logger(service id, defaults to null) andlogging_options.level(enum over the eight PSR-3 levels, defaults toerror)src/DependencyInjection/ItkDevOpenIdConnectExtension.php- wire both onto the bundle's own services and, viaregisterForAutoconfiguration(), onto consumer authenticator subclassessrc/Resources/config/services.yaml-monolog.loggerchannel tag (openid_connect) so consumers can route or alert on these logs; inert without MonologBundlecomposer.json- addpsr/logtorequire; it was only present transitivelytests/TestLogger.php- new in-memory PSR-3 spy;psr/log3 ships no test double and every log call needs an assertion to survive InfectionREADME.md,CHANGELOG.mdTest Plan
task test:coverage— 106 tests, coverage 100% (9/9 classes, 30/30 methods, 319/319 lines)task test:mutation— 147/147 mutants killed, Covered Code MSI 100% (threshold 95)task analyze:php— PHPStan max level + custom exception-contract rules: no errors, no new ignorestask test:matrix— PHP 8.3/8.4/8.5 × prefer-lowest/prefer-stable: all 6 passtask lint:php,lint:markdown,lint:yaml,composer validate --strict,composer normalize --dry-run— all cleanEvery log assertion checks level, message, and context (including that the causing exception reaches
context['exception']), and the success paths assert that nothing is logged.Note on the base branch
Stacked on #53, which touches the same authenticator. Retarget to
developonce that merges.