Skip to content

Instantly share code, notes, and snippets.

@slavafomin
Last active September 4, 2022 17:59
Show Gist options
  • Save slavafomin/4e0b70a39d1cff23af0f to your computer and use it in GitHub Desktop.
Save slavafomin/4e0b70a39d1cff23af0f to your computer and use it in GitHub Desktop.

Revisions

  1. Slava Fomin revised this gist Mar 3, 2015. 2 changed files with 58 additions and 0 deletions.
    50 changes: 50 additions & 0 deletions UsernamePasswordFormAuthenticationListener.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    <?php

    namespace App\Security;

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener as BaseClass;
    use App\Model\User;
    use App\Repository\UserRepository;


    class UsernamePasswordFormAuthenticationListener extends BaseClass
    {
    /** @var UserRepository */
    protected $userRepository;


    /**
    * @param UserRepository $userRepository
    */
    public function setUserRepository(UserRepository $userRepository)
    {
    $this->userRepository = $userRepository;
    }

    /**
    * @param Request $request
    *
    * @return null|Response|TokenInterface
    */
    protected function attemptAuthentication(Request $request)
    {
    $result = parent::attemptAuthentication($request);

    if ($result instanceof TokenInterface) {

    /** @var User $user */
    $user = $result->getUser();

    if ($user->isForceLogout()) {
    // Clearing this flag.
    $user->setForceLogout(false);
    $this->userRepository->save($user);
    }
    }

    return $result;
    }
    }
    8 changes: 8 additions & 0 deletions services.yml
    Original file line number Diff line number Diff line change
    @@ -15,3 +15,11 @@ services:
    event: kernel.request
    method: onKernelRequest
    priority: 0

    # Overriding Symfony's default login listener
    security.authentication.listener.form:
    class: WA\AppBundle\Security\UsernamePasswordFormAuthenticationListener
    parent: security.authentication.listener.abstract
    abstract: true
    calls:
    - [setUserRepository, [@app.repository.user]]
  2. Slava Fomin created this gist Mar 3, 2015.
    144 changes: 144 additions & 0 deletions ForcedLogoutListener.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,144 @@
    <?php

    namespace App\Security;

    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Session\SessionInterface;
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    use Symfony\Component\Routing\RouterInterface;
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
    use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
    use App\Model\User;
    use App\Repository\UserRepository;


    class ForcedLogoutListener
    {
    /** @var TokenStorageInterface */
    protected $tokenStorage;

    /** @var AuthorizationCheckerInterface */
    protected $authChecker;

    /** @var SessionInterface */
    protected $session;

    /** @var RouterInterface */
    protected $router;

    /** @var UserRepository */
    protected $userRepository;

    /** @var string */
    protected $sessionName;

    /** @var string */
    protected $rememberMeSessionName;


    /**
    * @param TokenStorageInterface $tokenStorage
    * @param AuthorizationCheckerInterface $authChecker
    * @param SessionInterface $session
    * @param RouterInterface $router
    * @param UserRepository $userRepository
    * @param string $sessionName
    * @param string $rememberMeSessionName
    */
    public function __construct(
    TokenStorageInterface $tokenStorage,
    AuthorizationCheckerInterface $authChecker,
    SessionInterface $session,
    RouterInterface $router,
    UserRepository $userRepository,
    $sessionName,
    $rememberMeSessionName
    ) {
    $this->tokenStorage = $tokenStorage;
    $this->authChecker = $authChecker;
    $this->session = $session;
    $this->router = $router;
    $this->userRepository = $userRepository;
    $this->sessionName = $sessionName;
    $this->rememberMeSessionName = $rememberMeSessionName;
    }

    /**
    * @param GetResponseEvent $event
    *
    * @return RedirectResponse|void
    */
    public function onKernelRequest(GetResponseEvent $event)
    {
    if (!$event->isMasterRequest() || !$this->isUserLoggedIn()) {
    return;
    }

    $accessToken = $this->tokenStorage->getToken();

    /** @var User $user */
    $user = $accessToken->getUser();

    // Forcing user to log out if required.
    if ($user->isForceLogout()) {

    // Logging user out.
    $response = $this->getRedirectResponse('app.login');
    $this->logUserOut($response);

    // Saving the user.
    $user->setForceLogout(false);
    $this->userRepository->save($user);

    // Setting redirect response.
    $event->setResponse($response);
    }
    }

    protected function isUserLoggedIn()
    {
    try {
    return $this->authChecker->isGranted('IS_AUTHENTICATED_REMEMBERED');
    } catch (AuthenticationCredentialsNotFoundException $exception) {
    // Ignoring this exception.
    }

    return false;
    }

    /**
    * @param string $routeName
    *
    * @return RedirectResponse
    */
    protected function getRedirectResponse($routeName)
    {
    return new RedirectResponse(
    $this->router->generate($routeName)
    );
    }

    /**
    * @param Response $response
    */
    protected function logUserOut(Response $response = null)
    {
    // Logging user out.
    $this->tokenStorage->setToken(null);

    // Invalidating the session.
    $this->session->invalidate();

    // Clearing the cookies.
    if (null !== $response) {
    foreach ([
    $this->sessionName,
    $this->rememberMeSessionName,
    ] as $cookieName) {
    $response->headers->clearCookie($cookieName);
    }
    }
    }
    }
    17 changes: 17 additions & 0 deletions services.yml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    services:

    app.security.forced_logout_listener:
    class: App\Security\ForcedLogoutListener
    arguments:
    - @security.token_storage
    - @security.authorization_checker
    - @session
    - @router
    - @app.repository.user
    - %app.session.name%
    - %app.session.remember_me.name%
    tags:
    - name: kernel.event_listener
    event: kernel.request
    method: onKernelRequest
    priority: 0