ssuperczynski
ssuperczynski

Reputation: 3416

Symfony2 FOS, redirect when not logged in

I'd like to redirect user to login page when nobody is not logged in. I wrote lister to that, but all the time I'm getting ERR_TOO_MANY_REDIRECTS error. Maybe is another method to achieve it globaly, and redirect user. Checking if user is logged in every controller is not a solution.

Listener\AccessListener.php

namespace Main\UserBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\SecurityContext;

class AccessListener{

    private $security;
    private $router;

    public function __construct($security, $router){
        $this->security = $security;
        $this->router = $router;
    }

    public function onKernelRequest(GetResponseEvent $event){
        if ($event->isMasterRequest()) {
            if( $this->security->isGranted('IS_AUTHENTICATED_REMEMBERED') ){
                $url = $this->router->generate('fos_user_security_login');
                $event->setResponse(new RedirectResponse($url));
            }
        }
    }
}

security.yml

security:
    access_denied_url: /login
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
                always_use_default_target_path: false
                default_target_path:            /
            logout:       true
            anonymous:    true

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN }

How do I correct it?

Upvotes: 1

Views: 3626

Answers (2)

qooplmao
qooplmao

Reputation: 17759

Your listener is checking whether a user is logged in and then, if they are not, they are being forwarded to the login page. At which point the listener checks whether the user is logged in... and so on.. and so on.

To stop this redirect loop you could check whether the current route being requested is the route that you are forwarding to, like so...

public function onKernelRequest(GetResponseEvent $event){
    if ($event->isMasterRequest()) {
        $loginRoute = 'fos_user_security_login';

        $request = $event->getRequest();

        // Return if current route and login route match
        if ($request->get('_route') === $loginRoute) {
            return;
        }

        if( $this->security->isGranted('IS_AUTHENTICATED_REMEMBERED') ){
            $url = $this->router->generate($loginRoute);
            $event->setResponse(new RedirectResponse($url));
        }
    }
}

However, a better way of doing this would be to add the root to the access control section needing a logged in user. This would allow you to have a better control over accessible and inaccessible paths.

access_control:
    ... current stuff ...
    - { path: ^/, role: ROLE_USER }

Upvotes: 4

Debreczeni András
Debreczeni András

Reputation: 1678

You need to check whether the current security context holds (or in your case if it does not hold) a fully authenticated user session as follows:

if( false == $this->security->isGranted('IS_FULLY_AUTHENTICATED') ){

Upvotes: 0

Related Questions