After a lot of search in the web and find nothing, I wonder if there is an easy way to automatic logout the user logged through the Symfony Security after an inactive period. I want that the user be logged out after 30 minutes of inactivity, for example.
I use a custom User Provider like this.
But after the user login into the system, the session never expires. Even if he close the browser and open it again after some days the session is still valid.
There is anyway to logout this user by an automatic way or even a manual way? How can I do that?
You have to implement it with a kernel listener, this is the way I solve it:
Listener src/Comakai/MyBundle/Handler/SessionIdleHandler.php
namespace Comakai\MyBundle\Handler;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class SessionIdleHandler
{
protected $session;
protected $securityToken;
protected $router;
protected $maxIdleTime;
public function __construct(SessionInterface $session, TokenStorageInterface $securityToken, RouterInterface $router, $maxIdleTime = 0)
{
$this->session = $session;
$this->securityToken = $securityToken;
$this->router = $router;
$this->maxIdleTime = $maxIdleTime;
}
public function onKernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST != $event->getRequestType()) {
return;
}
if ($this->maxIdleTime > 0) {
$this->session->start();
$lapse = time() - $this->session->getMetadataBag()->getLastUsed();
if ($lapse > $this->maxIdleTime) {
$this->securityToken->setToken(null);
$this->session->getFlashBag()->set('info', 'You have been logged out due to inactivity.');
// Change the route if you are not using FOSUserBundle.
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_security_login')));
}
}
}
}
Config src/Comakai/MyBundle/Resources/config/services.yml (Comakai/MyBundle/DependencyInjection/MyBundleExtension.php)
services:
my.handler.session_idle:
class: Comakai\MyBundle\Handler\SessionIdleHandler
arguments: ["@session", "@security.context", "@router", %session_max_idle_time%]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Now you can set the session_max_idle_time
in parameters.yml to 30 * 60 = 1800 seconds (or just hardcode the value wherever you want):
Parameters app/config/parameters.yml
parameters:
...
session_max_idle_time: 1800
The following setting will log out users that are inactive for more than 30minutes. If a request is made every 29minutes, they will never be logged out. Please note that this is not easy to test in an local environment as the garbage collector is only called from your request thus the gc_maxlifetime is never reached!
#app/config/config.yml
session:
cookie_lifetime: 86400
gc_maxlifetime: 1800
You can test this if you open more browsers/sessions and use the following config:
#app/config/config.yml
session:
cookie_lifetime: 86400
gc_maxlifetime: 1800
gc_probability: 1
gc_divisor: 1
Hope that helps!
Please note, adding:
session:
gc_probability: 1
gc_divisor: 1
Is only meant for testing the garbage collector on a local environment where there are no other requests that cause the garbage collector to remove your session. Making the garbage collector run on every request is not meant (or necessary) on a productive environment!
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