Persist failed authentication login attempts in Symfony2

3.7k Views Asked by At

I am using Symfony2 and need to save the failed login attempts to the database.

I have the following methods which I think I should be using:

// Symfony/Component/Security/Http/Autentication/AbstractAuthenticationListener.php
onFailure()
onSuccess()

But I am not sure how to access the database connection from within them.

How could run a database insert from within these functions?

2

There are 2 best solutions below

0
Jon Winstanley On BEST ANSWER

You need to define your own failure handler in security.yml

        form_login:
            provider:        fos_userbundle
            login_path:      /user/login
            csrf_provider:   form.csrf_provider
            failure_handler: myBundle.login.failure

Create a service to handle the failures

bundle.login.failure:
    class: 'MyBundle\Services\AuthenticationFailureHandler'
    arguments: ['@kernel']

Then build your failure handler:

<?php

namespace MyBundle\Services;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
    public function __construct(HttpKernelInterface $httpKernel)
    {
        $this->httpKernel = $httpKernel;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        // the auth just failed :-(
    }
}

To save attempts to the database inject your Doctrine manager into the service and persist the attempt from within the onFail method.

1
TautrimasPajarskas On

Just for logging there is an easy way by using security.authentication.failure listener. See Symfony documentation. You could use this blog post on how to persist logs to the actual database.

namespace AppBundle\EventListener;

use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;

class AuthenticationFailureListener implements LoggerAwareInterface
{
    use LoggerAwareTrait;

    public function onFailure(AuthenticationFailureEvent $event)
    {
        $token = $event->getAuthenticationToken();
        $username = $token->getUsername();
        $this->logger->info('Authentication failed', ['username' => $username]);
    }
}

And in services.yml

app.authentication_failure_listener:
    class: AppBundle\EventListener\AuthenticationFailureListener
    calls:
        - [setLogger, ['@logger']]
    tags:
        - { name: monolog.logger, channel: security }
        - { name: kernel.event_listener, event: security.authentication.failure, method: onFailure }