inpsyde / Wonolog

Monolog-based logging package for WordPress.
https://inpsyde.github.io/Wonolog/
MIT License
173 stars 17 forks source link

Possible to change default listener priority? Re: FailedLoginListener #61

Closed thefrosty closed 3 years ago

thefrosty commented 3 years ago

Describe the bug With the addition of Application Passwords in core (for some time now), I have noticed an increase in Security Notices for the FailedLoginListener action. Since wp_authenticate returns a null user on a REST request using Basic Auth via Application Password before priority 20 (in my quick tests), is there a way to change the action listener to a later priority?

To Reproduce

  1. Add user with Application Password
  2. Make REST request with Basic Auth.
  3. Repeat request three times and note SECURITY.NOTICE from Wonolog, but valid responses in REST call with no mention of authentication_failed WP_Error.

Expected behavior No NOTICE logged.

System (please complete the following information):

gmazzap commented 3 years ago

Hi,

Sorry had not time to reproduce yet, but yes, priority can be controlled, there a filter for that. See: https://github.com/inpsyde/Wonolog/blob/b1af1bcc8bdec2bd153a323bbbf507166c9c8e1b/src/HookListener/HookListenersRegistry.php#L117

So what to need to do is someting like this:

// replace `123` with the priority you'd like for that hook
add_filter('wonolog.listened-hook-priority', fn($prio, $hook) => $hook === 'wp_login_failed' ? 123 : $prio, 10, 2);

// bootstrap Wonolog here...
Inpsyde\Wonolog\bootstrap();

Alternatively, there's also a more "structured" way to do it, which I don't think it makes sense if that's the only customization you're going to have.

Wonolog supports a HookPriorityInterface. If an hook listener implements it, you can decide the priority from its priority() method.

That means you could create a custom listener decorating the Wonolog listener, like this:

use  Inpsyde\Wonolog\HookListener\HookPriorityInterface;
use  Inpsyde\Wonolog\HookListener\ActionListenerInterface;
use  Inpsyde\Wonolog\HookListener\FailedLoginListener;
use  Inpsyde\Wonolog\HookListener\ListenerIdByClassNameTrait;

class MyFailedLoginListener implements ActionListenerInterface
{
    use ListenerIdByClassNameTrait;

    private FailedLoginListener $wonologListener;

    public function __construct()
    {
         $this->wonologListener = new FailedLoginListener();
    }

    public function priority()
    {
        // the priority you desire
        return 123;
    }

    public function listen_to()
    {
        return $this->wonologListener->listen_to();
    }

    public function update(array $args)
    {
       $this->wonologListener->update($args);
    }
}

Having that, you need to don't use all default Wonolog listeners, but choosing your listener as described in the docs:

Wonolog\bootstrap(Wonolog\USE_DEFAULT_HANDLER|Wonolog\LOG_PHP_ERRORS|Wonolog\USE_DEFAULT_PROCESSOR)
    ->use_hook_listener(new HookListener\MyFailedLoginListener()) // this is your listener
    ->use_hook_listener(new HookListener\CronDebugListener())
    ->use_hook_listener(new HookListener\DbErrorListener())
    ->use_hook_listener(new HookListener\HttpApiListener())
    ->use_hook_listener(new HookListener\MailerListener())
    ->use_hook_listener(new HookListener\QueryErrorsListener())
    ->use_hook_listener(new HookListener\WpDieHandlerListener());