Question

I want to force user to use HTTPS instead of HTTP but only after authentication. The only option I've found is forcing HTTPS on per controller/method basis. Anonymous users should only use HTTP.

How to set force-HTTPS only for authenticated users and force NOT to use HTTPS for unauthenticated users in all controllers in my bundle?

Again - this isn't about disabling HTTPS for authorisation page.

I want to use all the same controllers for authenticated and unauthenticated users but force those logged in to use HTTPS, and those who aren't to use HTTP. Basically add requirement for HTTPS for ALL controllers when the user is authenticated.

This question is Symfony 2 specific. I want to do it using Symfony mechanisms. I know how to detect this thing, but it will break Twig links. Symfony can automatically switch to HTTPS, I just want to know how to do it on per-user role basis, not per controller basis.

Was it helpful?

Solution

One would think the access controller would do this for us:

access_control:
    - { role: ROLE_USER, requires_channel: https }
    - { role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: http }

But, no... I think this would be a very nice feature though.

In that case, we can hack something together with a request listener using kernel events:

namespace YourBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;

class RequestListener
{
    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        // force ssl based on authentication
        if ($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 {
            if ($request->isSecure()) {
                $request->server->set('HTTPS', false);
                $request->server->set('SERVER_PORT', 80);
                $event->setResponse(new RedirectResponse($request->getUri()));
            }
        }
    }
}

Define your listener in config.yml under services:

myapp.request.listener:
    class: MyApp\MyBundle\EventListener\RequestListener
    tags:
        - { name: kernel.event_listener, event: kernel.request }

See Symfony Internals for details on events and the like.

OTHER TIPS

In Symfony 2.0.11 I get a redirection error. To solve this I've commented out the following lines in the listener.

class RequestListener {
    public function onKernelRequest(GetResponseEvent $event) {
        $request = $event->getRequest();

        // force ssl based on authentication
        if     ($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 {
            if ($request->isSecure()) {
                $request->server->set('HTTPS', false);
                $request->server->set('SERVER_PORT', 80);
                // $event->setResponse(new RedirectResponse($request->getUri()));
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top