Use forwarded protocol if a proxy is used

Created on 23 April 2020, about 4 years ago
Updated 24 January 2023, over 1 year ago

On some projects with complex hosting setups Drupal can think the consumer route is HTTP even though it is HTTPS.

For anyone struggling with this issue this patch enforces HTTPS when getting the consumer route.

A patch for Onelogin PHP SAML is also attached which changes the start of the URL from http:// to https:// when checking if the current page is the consumer route.

🐛 Bug report
Status

Needs review

Version

4.0

Component

Code

Created by

🇬🇧United Kingdom Robert Castelo

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States jproctor

    This looks like it should work, but I’m having a hard time testing it and I want to be sure I understand:

    Given:

    1. Reverse proxy server “www.example.com
      • Has (for this example) IP address 10.1.2.3
      • Forwards all requests to http://drupal.example.com
      • Correctly sets HTTP_X_FORWARDED_PROTO to https when handing a secure request
    2. Drupal server “drupal.example.com”
      • $settings['reverse_proxy'] = TRUE;
      • $settings['reverse_proxy_addresses'] = ['10.1.2.3']

    When a request comes in to https://www.example.com/saml/drupal_login/example_idp, it forwards the request to http://drupal.example.com/saml/drupal_login/example_idp.

    Without this patch, the <AuthnRequest> goes out with http://... in the useful URLs, but with this patch, it should be https://..., yes?

    To test this, I enabled debugging on /admin/config/people/saml_sp and tried

    curl -H "HTTP_X_FORWARDED_PROTO: https" http://drupal.example.com

    I get the same output regardless of whether I have the patch in place:

    [assertionConsumerService] => Array
        (
            [url] => http://d9.lndo.site/saml/consume
            [binding] => urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
         )
    

    It’s possible that my test environment — I’m doing everything on one machine and Drupal is running in a container — is not a sufficient way to test this because Docker or Træfik or something is getting in the way.

  • 🇺🇸United States jproctor

    Update: I guess I needed to stop staring at it for a little while.

    Yes, Træfik was in the way, but I was able to get around it (and also specify the header correctly because ugh PHP), and now it seems to work regardless of whether I have the patch:

    curl -H "X-FORWARDED-PROTO: https" http://localhost:57961/saml/drupal_login/example_idp

    [assertionConsumerService] => Array
        (
            [url] => https://localhost:57961/saml/consume
            [binding] => urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
         )
    
  • 🇧🇪Belgium Matthijs

    I think your verifying the behavior at the wrong place. The problem is that \OneLogin\Saml2\Utils::getSelfURLhost() will return an http URL because it doesn't detect https unless you instruct it to read the forwarded headers.

    Also while testing don't forget to set the X-Forwarded-For header as well.

  • 🇺🇸United States jproctor

    Right, but we care about that because it generates the ACS URL in the <AuthnRequest>. Is there a post-login validation step that fails if OneLogin has the wrong URL (http) even if the right one (https) goes out to the IdP?

    I do have one other question: do we need a service for this, or could we do it in the controllers where we initiate and consume the exchange with the IdP?

  • First commit to issue fork.
Production build 0.69.0 2024