I have a User
entity, which has a boolean column isActivated
. Depending on the value of the column for each user, he may or may not be able to login (i.e. he hasn't activated his account so no login). I've achieved that by assigning an simple_form.authenticator
in the firewall which check upon every login.
I'm trying to figure out how force logout a user while he's still loged in.
Consider the following scenario:
Unfortunately step #3 doesn't happen. The reason may lay in the fact that the user has already received the token and is considered to be "tursted" by the Symfony 2.5
's firewall (probably the token is cached in the security context?).
I'm wondering what would be the best way to overcome this issue? Should I write a kernel event listener or perhaps a Custom User Provider?
You can terminate the user's session with the following two lines (if you have access to the container, otherwise you must inject security.context
and session
):
$container->get('security.context')->setToken(null);
$container->get('session')->invalidate();
After that, the user should be logged out.
If you have loaded the user entity before, you may want to unset that, too.
Although @lxg answered my question, I decided to extend his answer so that other people with the same issue have a better idea of how to fix that issue.
Create the event listener
namespace Acme\MyBundle\Events;
use Acme\MyBundle\Entity\User;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\SecurityContext;
class RequestEvent {
/**
* @var \Symfony\Component\Security\Core\SecurityContext
*/
private $securityContext;
public function __construct(SecurityContext $context){
$this->securityContext = $context;
}
public function onKernelRequest(GetResponseEvent $event)
{
// not sure if this is actually needed?
if (!$event->isMasterRequest()) {
// don't do anything if it's not the master request
return;
}
// try to get security context and catch the exception in case no firewall was configured (i.e. for the dev tool bar)
try{
// trigger only for logged in users
if($this->securityContext->isGranted('IS_AUTHENTICATED_FULLY')){
$token = $this->securityContext->getToken();
/**
* @var User $user
*/
$user = $token->getUser();
if($user != null && !$user->isActive()){
$this->securityContext->setToken(null);
}
}
} catch(AuthenticationCredentialsNotFoundException $e){
// don't do anything here... or do whatever you want.
}
}
}
?>
Now in your service.yml
add this:
services:
kernel.listener.request_listener:
class: Acme\MyBundle\Events\RequestEvent
arguments: [ @security.context ]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
And once the user has been deactivated, he'll be force-redirected to the login page of your firewall. Hope this helps somebody.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With