How to force access via HTTPS (HTTP over SSL) in Symfony 3


The SSL encryption is a good way to safeguard your data and user logins from being intercepted and read by outsiders. If you want to secure some routes in and make sure that they are always accessed via the HTTPS protocol in a Symfony project, you'll need to specify either in a single route or by specifying a custom rule in the access_control option of the security.yml file.

Requirements

  • You will need a valid SSL certificate before you can enable HTTPS in your server related to your domain. You can choose to create a self-signed certificate or to buy a certificate issued by a certificate authority (CA).

Suggestion

If you are looking for a SSL certificate, we recommend you to visit Cheap SSL Shop. SSL Certificates offered by Cheap SSL Shop are from globally trusted SSL brands like RapidSSL, Thawte, GeoTrust, GlobalSign, Comodo, Symantec (VeriSign) and they can be as cheap as $4.95 / year.

In case you don't want to pay for a SSL certificate, we recomend you to try Let's Encrypt, the free, automated, and open Certificate Authority. 

Once you're sure that your server has a SSL valid certificate, then proceed to force this protocol in your Symfony project. Note that even after you have a SSL certificate installed and available, symfony won't force HTTPS unless you do.

Implementation

Currently in Symfony 3 there are two ways to enable HTTPS:

A. Single route

To force the HTTPS connection in a single route, use the schemes options and set it to https: 

mainbundle_route_identifier:
    path:     /route-name
    defaults: { _controller: sandboxmainBundle:Default:action_controller}
    # Force HTTPS
    schemes: [https]

Example in a routing.yml file of a random bundle:

## Project accesible at http://project.com/

# 1. None scheme set, http used by default

mainbundle_homepage: # http://project.com/
    path:     /
    defaults: { _controller: sandboxmainBundle:Default:index}
mainbundle_contact: # http://project.com/conctact
    path:     /contact
    defaults: { _controller: sandboxmainBundle:Default:contact}

# 2. Secured by forcing HTTPS in the routes

mainbundle_blog: # https://project.com/blog
    path:     /blog
    defaults: { _controller: sandboxmainBundle:Default:blog}
    schemes: [https]
mainbundle_login: # https://project.com/login
    path:     /login
    defaults: { _controller: sandboxmainBundle:Default:login}
    schemes: [https]

B. Add security rules

The Security component provides another way to enforce HTTP or HTTPS via the requires_channel setting. This alternative method is better suited to secure an "area" of your website (all URLs under /admin) instead of specify manually every route.

You can modify the /app/config/security.yml file to specify which URLs of your app will have by adding a new rule for a route inside the access_control property of the security.yml file. This roule needs to contain 3 properties:

  • path: The route that matches the rule.
  • roles: The roles in which this rule will be applied.
  • requires_channel: the protocol to force (in this case https).

The following example shows how to enable HTTPS for all the routes inside your project with the IS_AUTHENTICATED_ANONYMOUSLY role (anyone that uses the project):

security:
    # ... #
    access_control:
        - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

or only for the login path:

security:
    # ... #
    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

Creating routes

Symfony will take care automatically of generate the routes with HTTP or HTTPS according to the settings either with Twig or PHP (in the controllers), so you don't need to worry about what would happen if the user is in a secured route but is redirected to a insecure route (anyway if some extraordinary happens, if you set requires_channel or schemes it will be automatically redirected).

If you generate a URL of a secured route, and if the current scheme is HTTP, Symfony will automatically generate an absolute URL with HTTPS (including domain https://domain.com/secure-route).

Note: now that HTTPS is enabled and available, the old HTTP (insecure) routes won't be available anymore because you're forcing the encryption, symfony will redirect the HTTP URLs to their HTTPS equivalent.

Have fun !

Become a more social person