Skip to content

Authentication exceptions logged before having the chance to get handled #27440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spantaleev opened this issue May 31, 2018 · 11 comments
Closed

Comments

@spantaleev
Copy link

Symfony version(s) affected: 4.1.0

Description

Seems like ever since #25366, authentication exceptions are first logged, and then handled gracefully (redirecting to a login entrypoint).

If an unauthenticated user hits a route they cannot access (e.g. a homepage route with this firewall rule - { path: ^/, role: ROLE_ADMIN }), what currently happens is:

  • step 1: Symfony\Component\Security\Http\Firewall\AccessListener rightfully throws an AccessDeniedException exception

  • step 2: because of its new and high priority level (of 2048 since [HttpKernel] Decouple exception logging from rendering #25366), Symfony\Component\HttpKernel\EventListener\ExceptionListener decides to log this exception: Uncaught PHP Exception AccessDeniedException .... Logging such a CRITICAL error has the bad side-effect of causing Monolog to send me an email.

  • step 3: because of its (now-comparatively-low) priority level of 1, Symfony\Component\Security\Http\Firewall\ExceptionListener gets triggered. It converts the exception to a (redirect) Response (to the login page), and the website appears to work. However, it's way too late already, as "step 2" (above) already logged the error and sent me an exception email.

Possible Solution

Symfony\Component\Security\Http\Firewall\ExceptionListener can be executed with a higher priority than Symfony\Component\HttpKernel\EventListener\ExceptionListener, so that graceful handling of authentication exceptions can happen before logging.

Changing Symfony\Component\Security\Http\Firewall\ExceptionListener, so that the KernelEvents::EXCEPTION priority is higher (from 1 to 2049) works around the problem.

@senaria
Copy link
Contributor

senaria commented Jun 4, 2018

The exact same problem you described also happens for access denied exceptions.

@lyrixx
Copy link
Member

lyrixx commented Jun 5, 2018

I confirm this issue (I did not see it earlier, so I dig a bit :/ )

Here are the logs for the different version of Symfony:

With SF 3.4
===========

[2018-06-05 10:44:22] request.INFO: Matched route "homepage". {"route":"homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"homepage"},"request_uri":"http://127.0.0.1:8000/","method":"GET"} []
[2018-06-05 10:44:22] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /tmp/security/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php:51)"} []
[2018-06-05 10:44:22] security.DEBUG: Calling Authentication entry point. [] []


With SF 4.0
===========

[2018-06-05 10:51:56] request.INFO: Matched route "homepage". {"route":"homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"homepage"},"request_uri":"http://127.0.0.1:8000/","method":"GET"} []
[2018-06-05 10:51:56] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /tmp/security/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php:51)"} []
[2018-06-05 10:51:56] security.DEBUG: Calling Authentication entry point. [] []


With SF 4.1
===========
[2018-06-05 10:53:01] request.INFO: Matched route "homepage". {"route":"homepage","route_parameters":{"_route":"homepage","_controller":"AppBundle\\Controller\\DefaultController::indexAction"},"request_uri":"http://127.0.0.1:8000/","method":"GET"} []
[2018-06-05 10:53:01] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException: "A Token was not found in the TokenStorage." at /tmp/security/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php line 51 {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /tmp/security/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php:51)"} []
[2018-06-05 10:53:01] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /tmp/security/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php:51)"} []
[2018-06-05 10:53:01] security.DEBUG: Calling Authentication entry point. [] []

@nicolas-grekas
Copy link
Member

Ping @ro0NL FYI.
Would anyone like to have a look and send a PR?

@ThomasTr
Copy link
Contributor

ThomasTr commented Jun 6, 2018

It seems that excluded_http_codes also doesen't work.

With this config:

monolog:
    handlers:
        main:
            type:                fingers_crossed
            excluded_http_codes: [403, 404]
            action_level:        critical
            handler:             grouped
        grouped:
            type:    group
            members: [streamed, deduplicated]
        streamed:
            type:  stream
            path:  '%kernel.logs_dir%/%kernel.environment%.log'
            level: debug
        deduplicated:
            type:    deduplication
            handler: swift
        swift:
            type:         swift_mailer
            from_email:   'thomas.trautner@bmgmis.de'
            to_email:     'thomas.trautner@bmgmis.de'
            subject:      'An Error Occurred! %%message%%'
            level:        debug
            formatter:    monolog.formatter.html
            content_type: text/html

I still get 403 "Access denied" errors.

@ro0NL
Copy link
Contributor

ro0NL commented Jun 6, 2018

In general i'd like to raise the security exception listener to 2049, sure. But it's quite significant.. and im afraid it affects some users.

We could lower the logging a bit from 2048 to maybe just 10 or so, so the security listener would get 11. But conceptually it's the same problem... changing priorities is tricky.

Another solution would be to introduce a pointer interface to mark exceptions skipped from logging.

@lyrixx
Copy link
Member

lyrixx commented Jun 6, 2018

Another solution would be to introduce a pointer interface to mark exceptions skipped from logging.

Like it ;)

@nicolas-grekas
Copy link
Member

Or log exceptions at -64?

@ro0NL
Copy link
Contributor

ro0NL commented Jun 8, 2018

@nicolas-grekas the intend was to log at high prio, so that it works independent from userland listeners. Those are typically defined with prio > 0 (and most likely < 2048 :)). The issue is it potentially disables logging, hence the PR to decouple it.

That said, i think we should revert it :) given the conflict with the security exception listener. However i'd prefer to meet in the middle, e.g.

  • security at 513
  • log/collect at 512
  • render at 0

@ro0NL
Copy link
Contributor

ro0NL commented Jun 8, 2018

Moreover, we could trigger a deprecation in case there are userland listeners with prio between 0 and 512, in effort to change the prio in 5.0

@lyrixx
Copy link
Member

lyrixx commented Jun 8, 2018

@ro0NL There are legit use case to be between 0 & 512 ; In our app we have a LocaleListener

And on another app there is API Platform (so many listeners)

@ro0NL
Copy link
Contributor

ro0NL commented Jun 9, 2018

@lyrixx it would affect exception listeners only ...
@nicolas-grekas rendering happens at -128 in fact :) so i misunderstood your -64 suggestion i guess.

we can log exceptions with with prio 0 (security is prio 1). This creates a range from 0 to -128 for userland listeners to overwrite rendering and preserve standard logging.

fabpot added a commit that referenced this issue Jun 10, 2018
This PR was squashed before being merged into the 4.1 branch (closes #27562).

Discussion
----------

[HttpKernel] Log/Collect exceptions at prio 0

| Q             | A
| ------------- | ---
| Branch?       | 4.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no, fixes one
| Deprecations? | no
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | #27440
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

So that it runs after the security exception listener, which runs at prio 1.

Im not sure what to do with the (wrong) changelog entry for 4.1.0 at this point.. should we add a new entry for 4.1.1?

Commits
-------

85b832b [HttpKernel] Log/Collect exceptions at prio 0
@fabpot fabpot closed this as completed Jun 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants