symfonysymfony2

How can I force authenticated user to HTTPS in Symfony2 after fully authentication only?


I need to use https in Symfony 2.2 but only if user is fully authenticated.


Solution

  • Just got solution using onKernalRequest event listener.

    My onKernelRequest event service :

    <?php
    
    namespace Acme\DemoBundle\Listener;
    
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpKernel\HttpKernelInterface;
    
    /**
     * force https for fully authenticated user
     */
    class ForceHttpsListner
    {
    
        /**
         * container
         * 
         * @var type 
         */
        private $container;
    
        /**
         * 
         * @param type $container
         */
        public function __construct($container)
        {
            $this->container = $container;
        }
    
        /**
         * on kernel request
         * 
         * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
         */
        public function onKernelRequest(GetResponseEvent $event)
        {
    
            //all urls which always use https, specefied using requires_channel in security.yml
            $httpsPaths= [
                '/login',
                '/resetting/request',
                '/register/',
            ];
    
            if ($event->getRequestType() === HttpKernelInterface::MASTER_REQUEST ) {
    
                $request = $event->getRequest();
    
                if ($this->container->get('security.context')->getToken()
                        && $this->container->get('security.context')
                                ->isGranted('IS_AUTHENTICATED_FULLY')) {
    
                    if (!$request->isSecure()) {
    
                        $request->server->set('HTTPS', true);
                        $request->server->set('SERVER_PORT', 443);
                        $event->setResponse(new RedirectResponse($request->getUri()));
    
                    }
    
                } else {
    
                    //echo $request->getPathInfo(); exit;                
                    if ($request->isSecure() 
                            && !in_array($request->getPathInfo(), $httpsPaths)) {
    
                        $request->server->set('HTTPS', false);
                        $request->server->set('SERVER_PORT', 80);
                        $event->setResponse(new RedirectResponse($request->getUri()));
                    }
    
                }
    
            }
    
        }
    }
    

    Register service

    services:
        kernel.listener.forcehttps:
            class: Acme\DemoBundle\Listener\ForceHttpsListner
            tags:
                - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
            arguments: [ @service_container ]
    

    access_control in security.yml

    security:
        access_control:
            - { path: ^/_wdt, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/_profiler, role: IS_AUTHENTICATED_ANONYMOUSLY }        
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            - { path: ^/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    
            - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    
            # Secured part of the site
            # This config requires being logged for the whole site and having the admin role for the admin part.
            # Change these rules to adapt them to your needs
            - { path: ^/admin, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN, ROLE_SUPER_EDITOR] }
            - { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }