how to make the onAuthenticationSuccess function being called

13,097

Solution 1

You can listen for the event that is triggered after a successful login attempt by registering a service to the related security tag:

app.login_listener:
    class: AppBundle\EventListener\LoginListener
    arguments:
        - @security.authorization_checker
        - @security.token_storage
    tags:
        - { name: kernel.event_listener, event: security.interactive_login, method: yourMethod }

Where yourMethod can contain the code you want to execute.

Solution 2

There are a lot of same issues on SO, github, google groups, most of them are unsolved.

Also, you should define a custom AuthenticationSuccessHandler rather than extending the default.

Example:

services.yml

login_success_handler:
    class:  YourBundle\EventListener\CustomAuthenticationSuccessHandler
    arguments:  ["@doctrine", "@router"]
    tags:
        - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }

CustomAuthenticationSuccessHandler.php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Routing\RouterInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Doctrine\ORM\EntityManager;

class CustomAuthenticationSuccessHandler {
    private $em;
    private $logger;

    public function __construct(EntityManager $em, RouterInterface $router) 
    {
        $this->em = $em;
        $this->router = $router;
    }

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    {
        $this->onAuthenticationSuccess($event->getRequest(), $event->getAuthenticationToken());
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token) 
    {    
        $user = $token->getUser();
        $user->eraseCredentials();        
        $user->addRole('ROLE_USER');

        $this->em->flush() // If you don't do this, your changes will not be saved.
        $response = new RedirectResponse($this->router->generate('your_success_route'));

        return $response;
    }
}

Don't need of manually set the success_handler in your form, because the SuccessHandler is an EventListener and will be used on the corresponding event.

Share:
13,097
mlwacosmos
Author by

mlwacosmos

I work for the health social security goverment company with Java and PHP technologies

Updated on June 22, 2022

Comments

  • mlwacosmos
    mlwacosmos almost 2 years

    I would like to have some action after a success authentification.

    I created a class extended DefaultAuthenticationSuccessHandler, and redefined the onAuthenticationSuccess function.

    Though the authentication is a success, the programm never goes to the function : why ?


    namespace my_name_space;
    
    use   Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Doctrine\ORM\EntityManager;
    use Symfony\Component\Security\Http\HttpUtils;
    use Symfony\Bridge\Monolog\Logger;
    
    
    class AuthenticationSuccessHandler extends DefaultAuthenticationSuccessHandler {
    private $em;
    private $logger;
    
    function __construct(Logger $logger, HttpUtils $httpUtils, EntityManager $em) {
        parent::__construct($httpUtils);
        $this->em = $em;
        $this->logger = $logger;
    }
    
    public function onAuthenticationSuccess(Request $request, TokenInterface $token) {
        $this->logger->info("onAuthenticationSuccess");
        $response = parent::onAuthenticationSuccess($request, $token);
        $token->eraseCredentials();        
        $token->getUser()->addRole('ROLE_USER');
    
        return $response;
    }
    

    }

    services:
    security.authentication.success.handler:
        class: MY\NAMESPACE\AuthenticationSuccessHandler
        arguments: ["@monolog.logger.php","@security.http_utils", "@doctrine.orm.default_entity_manager"]
    

    security.yml

    form_login:
                check_path: _security_check
                use_referer: true
                use_forward: true
                login_path: my_login
                success_handler: security.authentication.success.handler
    
  • mlwacosmos
    mlwacosmos about 8 years
    really... why can't i Use the default on success handler which should call the onAuthenticationSuccess method that I redefined ?
  • Rvanlaak
    Rvanlaak about 8 years
    Think the success_listener notation is wrong, instead of security.authentication.success.handler you should call the service "@security.authentication.success.handler".
  • mlwacosmos
    mlwacosmos about 8 years
    you mean in the security.yml ? I say it again (the constructor of this class is called)
  • Rvanlaak
    Rvanlaak about 8 years
    Think you are somehow trying to override / decorate the default service because the service keys are identical, see stackoverflow.com/questions/15918617/… and stackoverflow.com/questions/27826964/…
  • mlwacosmos
    mlwacosmos about 8 years
    I know this post and it is like mine.. but the method is not triggered
  • mlwacosmos
    mlwacosmos about 8 years
    well it does not work either for me... onSecurityInteractiveLogin is not called... let's wait for some other people if it works for them
  • chalasr
    chalasr about 8 years
    Very strange. Hope someone fix the problem. Don't forget to keep the code in your question same has your actual implementation.
  • chalasr
    chalasr about 8 years
    If you can, remove your whole listener to restart from zero and try this one gist.github.com/marydn/8061424
  • Mitch
    Mitch about 4 years
    works when i change to "@doctrine.orm.default_entity_manager" in symfony 5