Opened 5 years ago

Closed 5 years ago

Last modified 2 years ago

#12043 closed Uncategorized (invalid)

Incorrect redirect to http instead of https

Reported by: admin@… Owned by: nobody
Component: Core (Other) Version: 1.1
Severity: Normal Keywords: redirect http https
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

To reproduce on a secure django website - Django (1.1)/mod_wsgi (2.5)/Python (2.5):

  1. Verify that https://secure.example.com/admin/ works
  2. Now try https://secure.example.com/admin
  3. Note that it has redirected to http://secure.example.com/admin instead of https://secure.example.com/admin/

This also happens in various other circumstances where Django decides to do a redirect for you. E.g. after logging out and back in.

This is probably caused by changeset 3410 - fix for ticket 2092. Please take a look at these for insight.

Humorous note: The following rather dubious hack works great for me because all of my pages are https :)

    # Not recommended for general use!
    def is_secure(self):
        return True

The correct fix will involve figuring out the correct detection of the url scheme in all cases.

Change History (7)

comment:1 Changed 5 years ago by grahamd

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Those change sets aren't going to be most recent for is_secure(). This is because for WSGI the code was since changed to correctly use wsgi.url_scheme.

There is no issue with wsgi.url_scheme generation in mod_wsgi, so long as Django code still checking that then should be fine.

One possibility for problems is that your Apache isn't handling HTTPS but you are hosting it behind a front end server, such as nginx. WebFaction for example does this. In that case, that HTTPS was used isn't known by Apache as it only receives HTTP from front end. In this case, necessary for front end web server to set a special HTTP header which is then detected by Apache behind, which using certain directives in Apache can detect that and set HTTPS in request environment which mod_wsgi will detect and convert to appropriate value for wsgi.url_scheme.

So, are you 100 percent certain that your Apache is accepting HTTPS requests in the first place.

Have ou tried dumping out WSGI environment before it is passed into Django to see what it is passed. Use code examples in:

http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Tracking_Request_and_Response

to capture such information and post here.

comment:2 Changed 5 years ago by admin@…

It looks like you've got the right idea.

I am using Webfaction.

I haven't tried dumping out WSGI environment before it is passed into Django, but I assume that your hypothesis is correct.

When I dump request.META (inside my Django view), I get:

  • wsgi.url_scheme = http
  • HTTP_X_FORWARDED_PROTO = https

So there are two possible solutions:

  1. I get Webfaction to do as you suggest (to fix wsgi.url_scheme).
  2. You change is_secure() to include HTTP_X_FORWARDED_PROTO in it's calculation.
  3. Do both.

Option 3 seems the most solid to me.

I'm sending Webfaction a link to this ticket.

comment:3 Changed 5 years ago by grahamd

Django does not need to be modified and WebFaction doesn't need to do anything for you.

Just add yourself to your Apache configuration for your Django site:

SetEnvIf X-Forwarded-Proto https HTTPS=1

WebFaction does this as part of their standard one click installers now. You obviously created yours back before they added this line to correspond to what header they have nginx set.

You may need to also load Apache module mod_setenvif.

comment:4 Changed 5 years ago by kmtracey

  • Resolution set to invalid
  • Status changed from new to closed

Closing since it sounds like this is a config issue, not a Django bug.

comment:5 Changed 2 years ago by simon@…

  • Easy pickings unset
  • Severity set to Normal
  • Type set to Uncategorized
  • UI/UX unset

I'm seeing the same thing on AWS Elastic Beanstalk, where the communication between the load balancer and EC2 hosts is over HTTP. I wrote a simple middleware class that tackles the issue, since I can't find a way to tweak the Apache config on those Elastic Beanstalk EC2 instances.

https://gist.github.com/3927386

class SecureRequestPropagationMiddleware(object):
    """
    When running on AWS Elastic Beanstalk, we suffer
    an issue where HTTPS requests arriving at the load
    balancer are propagated to the individual hosts as
    HTTP requests. If the host issues a redirect it
    issues it using the same scheme as its incoming
    request (HTTP) when it should use HTTPS.

    This issue isn't unique to AWS EB, it's discussed
    in the context of WebFaction hosting in this 
    Django ticket:

    https://code.djangoproject.com/ticket/12043

    This middleware addresses the problem, by
    using the value of the X-Forwarded-Proto header
    to manually set the wsgi.url_scheme header.
    """
    def process_request(self, request):
        if 'HTTP_X_FORWARDED_PROTO' in request.META:
            request.META['wsgi.url_scheme'] = request.META['HTTP_X_FORWARDED_PROTO']
        return None

comment:6 Changed 2 years ago by carljm

For future reference for those hitting this problem: Django 1.4+ now has a built-in solution in the form of the SECURE_PROXY_SSL_HEADER setting (https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header), so there's no need to write your own middleware.

comment:7 Changed 2 years ago by mes65@…

Also note that this issue affects clients on Google App Engine (and also probably Heroku, but I haven't tested) using the wwwizer service.

Note: See TracTickets for help on using tickets.
Back to Top