python flask redirect to https from http

Posted on

Question :

python flask redirect to https from http

I have a website build using python3.4 and flask…I have generated my own self-signed certificate and I am currently testing my website through localhost.

I am using the python ssl module along with this flask extension: https://github.com/kennethreitz/flask-sslify

context = ('my-cert.pem', 'my-key.pem')
app = Flask(__name__)
sslify = SSLify(app)

...

if __name__ == '__main__':
    app.debug = False
    app.run(
    host="127.0.0.1",
    port=int("5000"),
    ssl_context=context
)

This does not seem to be working however. I took a look in the sslify source code and this line does not seem to be working

def init_app(self, app):
    """Configures the configured Flask app to enforce SSL."""
    app.before_request(self.redirect_to_ssl)
    app.after_request(self.set_hsts_header)

Specifically the function call to redirect_to_ssl (I added my own print statement under the redirect_to_ssl function and my statement was never printed)

def redirect_to_ssl(self):
    print("THIS IS WORKING")
    """Redirect incoming requests to HTTPS."""
    Should we redirect?
    criteria = [
        request.is_secure,
        current_app.debug,
        request.headers.get('X-Forwarded-Proto', 'http') == 'https'
    ]

    if not any(criteria) and not self.skip:
        if request.url.startswith('http://'):
            url = request.url.replace('http://', 'https://', 1)
            code = 302
            if self.permanent:
                code = 301
            r = redirect(url, code=code)
            return r

I am pretty new to python. Any ideas?

Answer #1:

To me, it appears you’re making it more complicated than it needs to be. Here is the code I use in my views.py script to force user to HTTPS connections:

@app.before_request
def before_request():
    if request.url.startswith('http://'):
        url = request.url.replace('http://', 'https://', 1)
        code = 301
        return redirect(url, code=code)

Answer #2:

According with the docs, after pip install Flask-SSLify you only need to insert the following code:

from flask import Flask
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)

I have done it and it works very well. Am I missing something in the discussion ?

Answered By: Rodolfo Alvarez

Answer #3:

The Flask Security Guide recommends using Flask-Talisman.

$ pip install flask-talisman

Usage example:

from flask import Flask
from flask_talisman import Talisman

app = Flask(__name__)
Talisman(app)

It forces HTTPS by default (from the README):

force_https, default True, forces all non-debug connects to https.


Personally, I got some errors relating to CSP (Content Security Policy) which I disabled with:

Talisman(app, content_security_policy=None)

But use this at your own risk 🙂

Answered By: Eyal Levin

Answer #4:

Thanks to answer from Kelly Keller-Heikkila and comment by jaysqrd I ended up doing this in my Flask app:

from flask import request, redirect
...

@app.before_request
def before_request():
    if app.env == "development":
        return
    if request.is_secure:
        return

    url = request.url.replace("http://", "https://", 1)
    code = 301
    return redirect(url, code=code)

I tried the flask_sslify solution suggested by Rodolfo Alvarez but ran into this issue and went with the above solution instead.

If the app is running in development mode or the request is already on https there’s no need to redirect.

Answered By: anulaibar

Answer #5:

Here is a flask solution if you are on aws and behind a load balancer. Place it in your views.py

@app.before_request
def before_request():
    scheme = request.headers.get('X-Forwarded-Proto')
    if scheme and scheme == 'http' and request.url.startswith('http://'):
        url = request.url.replace('http://', 'https://', 1)
        code = 301
        return redirect(url, code=code)
Answered By: edW

Answer #6:

The standard solution is to wrap the request with an enforce_ssl decorator that after checking some flags in the app configuration (flags you can set depending on your debugging needs) modifies the request’s url with request.url.

As it is written here.

You can modify the code to make it working with before_request as suggested by @kelly-keller-heikkila

Answered By: tuned

Answer #7:

I use a simple extra app that runs on port 80 and redirect people to https:

from flask import Flask,redirect

app = Flask(__name__)

@app.route('/')
def hello():
    return redirect("https://example.com", code=302)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)
Answered By: Wietze

Answer #8:

I ran into the same solution running a Flask application in AWS Elastic Beanstalk behind a load balancer. The following AWS docs provided two steps to configure the environment for http redirects: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-httpredirect.html Following both steps fixed my issue.

One thing to note is that you’ll have to create the .ebextenions folder at the root level of your application source bundle and add the config file to that .ebextensions folder. The readme here: https://github.com/awsdocs/elastic-beanstalk-samples explains this in a bit more detail.

Answered By: Evan G

Leave a Reply

Your email address will not be published.