Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2: Check user authentication based on path

in Symfony2, is it possible to check if user is authenticated to access the URl he requested. What I want to do is, i dont want to allow a logged in user to go back to registration or login or recover password pages.

here is my security.yml:

    access_control:
    - { path: ^/signup/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/register/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/recover/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}

but this is showing, access denied page to current user. So i think it would be nice if I can redirect the user to home page on such request, by checking if he is not allowed. Can I check by providing path that user is authenticated or not in listener?

    public function onKernelResponse(FilterResponseEvent $event)
    {
     $request = $event->getRequest();
     $path = $request->getPathInfo();

     if($this->container->get('security.context')->getToken() != null) {
       // To check if user is authenticated or anonymous
       if( ($this->container->get('security.context')->getToken() instanceof UsernamePasswordToken) &&
        ($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') == true) ) {
         // HOW TO CHECK PATH ?
        // set response to redirect to home page
      }
    }
  }
like image 200
Tejas Gosai Avatar asked Nov 25 '13 12:11

Tejas Gosai


2 Answers

The security.access_map service

The configuration of security.access_control is processed by ...

SecurityBundle\DependencyInjection\SecurityExtension

... which creates RequestMatchers for the routes (path,hosts,ip,...) and then invokes the service's add() method with the matcher, the allowed roles and the channel (i.e. https ).

The service is usually used by i.e. the AccessListener.

You can use the security.access_map service to access the security.access_control parameters in your application.

The class used for the security.access_map service is defined by the parameter security.access_map.class and defaults to

Symfony\Component\Security\Http\AccessMap ( implements AccessMapInterface )

You can use the parameter security.access_map.class to override the service with a custom class (must implement AccessMapInterface):

# i.e. app/config/config.yml

parameters:
    security.access_map.class: My\Custom\AccessMap

How to access the service

The security.access_map service is a private service as you can see by it's definition here.

This means you can't request it from the container directly like this:

$this->container->get('security.access_map')

You will have to inject it into another service (i.e. a listener service) explicitly to be able to access it.


A listener example

services:
    my_listener:
        class: My\Bundle\MyListenerBundle\EventListener\ForbiddenRouteListener
        arguments: [ @security.access_map ]
        tags:      
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

Then you can call the getPatterns() method to obtain the RequestMatchers, allowed roles and required channel from there.

namespace My\Bundle\MyListenerBundle\EventListener;

use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class ForbiddenRouteListener
{

    protected $accessMap;

    public function __construct(AccessMapInterface $access_map)
    {
        $this->accessMap = $access_map;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $patterns = $this->accessMap->getPatterns($request);

        // ...
like image 179
Nicolai Fröhlich Avatar answered Nov 08 '22 07:11

Nicolai Fröhlich


Maybe this will help someone. I just catch route name and check if they are in array. If yes just redirect. This is event listener.

services.yml

project.loggedin_listener:
      class: Project\FrontBundle\EventListener\LoggedInListener
      arguments: [ "@router", "@service_container" ]
      tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

listener:

namespace Project\FrontBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;

class LoggedInListener {
    private $router;
    private $container;

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

    public function onKernelRequest(GetResponseEvent $event)
    {
        $container = $this->container;
        $accountRouteName = "_homepage";

        if( $container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') ){

            $routeName = $container->get('request')->get('_route');
            $routes = array("admin_login","fos_user_security_login","fos_user_registration_register","fos_user_resetting_request");
            if(in_array($routeName, $routes)){
                $url = $this->router->generate($accountRouteName);
                $event->setResponse(new RedirectResponse($url));
            }

        }

    }
}
like image 1
pregmatch Avatar answered Nov 08 '22 07:11

pregmatch