28

Issue:

security.yml:

security:

    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

    firewalls:
        main:
            pattern:    ^/
            form_login:
                check_path: /login_check
                login_path: /login
                default_target_path: /profile
                provider: fos_userbundle
            logout:
                path:   /logout
                target: /splash
            anonymous: ~

    access_control:
        - { roles: ROLE_USER, requires_channel: https }
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

    acl:
        connection: default

Environment Architecture:

enter image description here

The Server1 and Server2 holds Symfony2 application.

Question:

How to force Symfony to generate redirect URL with https protocol instead http?

So far I have looked at these docs, and the solution didn't work work in my case:

TeaCupApp
  • 11,316
  • 18
  • 70
  • 150
  • do you have schemes: [https] in your routing.yml? – Timur May 15 '14 at 11:21
  • Have tried that too, thanks for the response. Initially this cause infinity redirection then I added trusted_proxies: [10.0.0.0/8] into config.yml. The infinity redirection is now gone but Symfony still generates redirect URLs to be http not https. Thanks – TeaCupApp May 16 '14 at 23:26
  • I have this exact architecture working at AWS. Not sure why yours is not working. If the user just hit `example.com/login`, are they redirectef to `https` ? – Broncha May 22 '14 at 11:17
  • This applies, downstream, to apps deployed on Heroku also. – yitznewton Oct 23 '17 at 15:09

7 Answers7

21

Take a look at

vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/Request.php

AWS ELB's use HTTP_X_FORWARDED_PROTO and HTTP_X_FORWARDED_PORT while Symfony looks the X_FORWARDED_PROTO and X_FORWARDED_PORT headers to judge the connection and its secure status.

You can try changing those keys in the trustedHeaders although I would not recommend directly changing them but finding a way to override those.

protected static $trustedHeaders = array(
        self::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
        self::HEADER_CLIENT_HOST  => 'X_FORWARDED_HOST',
        self::HEADER_CLIENT_PROTO => 'HTTP_X_FORWARDED_PROTO',
        self::HEADER_CLIENT_PORT  => 'HTTP_X_FORWARDED_PORT',
    );

Reference - http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/TerminologyandKeyConcepts.html#x-forwarded-for

A23
  • 1,596
  • 2
  • 15
  • 31
  • Gosh, missed on replying for the question. I will try what you have suggested thanks – TeaCupApp May 23 '14 at 18:11
  • Thanks for this-- where in Symfony would you put the override code? – Acyra Jan 26 '15 at 14:58
  • In production - /web/app.php - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X-Proxy-For'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X-Proxy-Host'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X-Proxy-Port'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X-Proxy-Proto'); – A23 Jan 27 '15 at 00:48
8
  1. Make sure that trusted_hosts and trusted_proxies configuration properties are set appropriately.
  2. Make sure that your load balancer adds X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Port and, what's most important, X-Forwarded-Proto headers to the HTTP request send to the application.

Documentation: Trusting Proxies.


EDIT:

As @A23 suggested you should also check if ELB is using "standard" headers names. If not, change them using one of following:

Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X-Proxy-For');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X-Proxy-Host');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X-Proxy-Port');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X-Proxy-Proto');
Community
  • 1
  • 1
Crozin
  • 43,890
  • 13
  • 88
  • 135
  • 1
    I have trusted_proxies set to [10.0.0.0/8] and load balancer the headers are available and set as suggested. Still the redirected URL generated by Symfony is http instead https. Thanks – TeaCupApp May 16 '14 at 23:25
  • 1
    Could you post the result of `var_dump($request->isSecure())`. – Crozin May 19 '14 at 09:04
  • Sorry, missed out this Crozin. I will try your suggestions thank you – TeaCupApp May 23 '14 at 18:11
  • Just a note for anyone else who is climbing the walls - as of April '16, ELB seems to be forwarding the standard headers. At least with Elastic Beanstalk with PHP 5.6. YMMV! – Darragh Enright Apr 13 '16 at 23:40
2

I had the exact same problem with a PHP application using AWS and ELB with SSL in a CakePHP application.

My solution was good in some ways and bad in others. The problem was that Amazon sends different HTTPS headers than the PHP headers you look for: $_SERVER['HTTPS'] is off, while Amazon sends alternative HTTPS headers that you can use to identify that it is in fact running under HTTPS:

$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'

I worked out that my base URL constant that Cake defined internally had the http protocol in it, so I simply redefined the $_SERVER['HTTPS'] variable on the very first line of my index.php file in Cake - and I wouldn't be surprised if you could do the same in symfony):

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

This allowed my application to continue on, detect HTTPS as being 'on' as would normally be expected and allow Cake to internally manage the protocol in my base URL constant.

Good:

  • fixed the problem immediately
  • used 3 lines of code

Bad:

  • whenever I upgrade my Cake core, I'll have to put this back in again
scrowler
  • 24,273
  • 9
  • 60
  • 92
0

How to force Symfony to generate redirect URL with https protocol instead http?

You need to explicitly configure the HTTPS protocol because by detection alone, Symfony2 will only guess HTTP as HTTP is used as transport protocol to the application.

So for the component that creates the redirect URI, you need to inject the HTTPS base URI-Scheme. One simple way to do this, is to configure the base-URI as a parameter and then within the configuration.

Example codes are given

hakre
  • 193,403
  • 52
  • 435
  • 836
0

are you use absolute url for redirection? i was facing a similar issue behind myracloud when we used relative urls on redirection. myracloud "fixed" it and made it absolute, but lost the protocol.

oliver nadj
  • 788
  • 7
  • 21
0

I have solved this kind of issue in my .htaccess, it has the downside that it always redirects to https also not behind a S2 firewall, which is ok in my case since I only have the login form publicly available and I want the credentials to be sent via https

 RewriteCond %{HTTP:X-Forwarded-Proto} !https
 RewriteRule (.*) https://%{SERVER_NAME}/$1 [redirect=permanent,last]
m0c
  • 2,180
  • 26
  • 45
0

The solutions above did not work for me. I added the following line of code (as suggested in Symfony2's docs http://symfony.com/doc/current/cookbook/request/load_balancer_reverse_proxy.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly) to my web/app.php:

Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));

right after

$request = Request::createFromGlobals();

That solved the problem for me in Symfony 2.5.

totas
  • 10,288
  • 6
  • 35
  • 32
  • The Symony article mentions "Configure your web server(s) to not respond to traffic from any clients other than your load balancers. For AWS, this can be done with security groups". My security group is set to accept all HTTP and HTTPS traffic (i.e. to 0.0.0.0/0). Should I be doing something different? Note: I have a few routes that I don't want to serve on HTTPS. Thanks! – diazdeteran Dec 05 '15 at 22:22