can you add HTTPS functionality to a python flask web server?
Solution 1
this also works in a pinch
from flask import Flask, jsonify
from OpenSSL import SSL
context = SSL.Context(SSL.PROTOCOL_TLSv1_2)
context.use_privatekey_file('server.key')
context.use_certificate_file('server.crt')
app = Flask(__name__)
@app.route('/')
def index():
return 'Flask is running!'
@app.route('/data')
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
#if __name__ == '__main__':
# app.run()
if __name__ == '__main__':
app.run(host='127.0.0.1', debug=True, ssl_context=context)
Solution 2
Don't use openssl or pyopenssl its now become obselete in python
Refer the Code below
from flask import Flask, jsonify
import os
ASSETS_DIR = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__)
@app.route('/')
def index():
return 'Flask is running!'
@app.route('/data')
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
if __name__ == '__main__':
context = ('local.crt', 'local.key')#certificate and key files
app.run(debug=True, ssl_context=context)
Solution 3
- To run HTTPS functionality or SSL authentication in your flask application, first install "pyOpenSSL" python package
pip install pyopenssl
- Next step is to create
cert.pem
andkey.pem
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Copy generated
cert.pem
andkey.pem
in your flask application projectAdd
ssl_context=('cert.pem', 'key.pem')
inapp.run()
, like in the example below.
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/")
def index():
return "Flask is running!"
@app.route("/data")
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
if __name__ == "__main__":
app.run(ssl_context=("cert.pem", "key.pem"))
Solution 4
Deploy Flask on a real web server, rather than with the built-in (development) server.
See the Deployment Options chapter of the Flask documentation. Servers like Nginx and Apache both can handle setting up HTTPS servers rather than HTTP servers for your site.
The standalone WSGI servers listed would typically be deployed behind Nginx and Apache in a proxy-forwarding configuration, where the front-end server handles the SSL encryption for you still.
Solution 5
For a quick n' dirty self-signed cert, you can also use flask run --cert adhoc
or set the FLASK_RUN_CERT
env var.
$ export FLASK_APP="app.py"
$ export FLASK_ENV=development
$ export FLASK_RUN_CERT=adhoc
$ flask run
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on https://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 329-665-000
The adhoc
option isn't well documented (for good reason, never do this in production), but it's mentioned in the cli.py source code.
There's a thorough explanation of this by Miguel Grinberg at Running Your Flask Application Over HTTPS.
robm
Updated on October 13, 2021Comments
-
robm over 2 years
I am trying to build a web interface to Mock up a restful interface on networking device this networking device uses Digest Authentication and HTTPS. I figured out how to integrate Digest Authentication into the web server but I cannot seem to find out how to get https using FLASK if you can show me how please comment on what i would need to do with the code below to make that happen.
from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def index(): return 'Flask is running!' @app.route('/data') def names(): data = {"names": ["John", "Jacob", "Julie", "Jennifer"]} return jsonify(data) if __name__ == '__main__': app.run()
-
Graham Dumpleton about 9 yearsIf you use mod_wsgi-express (pypi.python.org/pypi/mod_wsgi) it provides an easy way of running up a site with HTTPS, plus has builtin capabilities for handling Digest authentication protocol at the web server level as well. Suggest you ask about it on the mod_wsgi mailing list as StackOverflow is not a discussion forum and so not as easily explained here.
-
OWADVL about 8 yearsSSLv3 has POODLE vulnerability. Change it to TSL
-
Pierre Cordier almost 8 yearsFollowing this link : flask.pocoo.org/snippets/111 At the end of the page a comment explains how to change to TSL.
-
Alexis.Rolland almost 7 years@Martijn Pieters, Could you please explain why we should "Deploy Flask on a real web server, rather than with the built-in (development) server."? Thanks
-
Martijn Pieters almost 7 years@Alexis.Rolland: the built-in server is not equipped to deal with the 'real world' of the internet, it has not been battlehardened from a security POV nor has it been tuned for performance. It's primary purpose is to bootstrap development on a local machine, nothing more. Using it in a production environment is at your own risk, which in my opinion is a rather large risk.
-
andyandy almost 7 yearsTo generate
local.crt
andlocal.key
see Method 2 of: kracekumar.com/post/54437887454/ssl-for-flask-local-development -
prayagupa over 6 yearsweird, it runs at
http://127.0.0.1:5000/
. is not this supposed to run on secure http. I Still can GET athttp://127.0.0.1:5000/
-
damaniel about 6 yearsYou mean TLS not TSL?
-
magor over 5 yearsusing a real webserver is not always an option, i just want to serve some files with Flask and https
-
Martijn Pieters over 5 years@mazs: then you take the security risk. And it's trivial to install gunicorn and use that to serve your Flask, that server at least is much more battle hardened.
-
KcH about 4 yearsi got an error after first step as
openssl' is not recognized as an internal or external command
-
vaishali KUNJIR about 4 yearsDid you installed pyopenssl?
-
KcH about 4 yearsyes i have installed ....later when I am trying step 2
to create 'cert.pem' and 'key.pem'
it shown me the error -
KetZoomer almost 4 yearsYou have to add it to path if you are in windows.
-
KetZoomer almost 4 yearsYou also have to download it. From the website, not from pip.
-
nimi almost 4 yearsThis code for creating the
context
is deprecated for newer python. Try this:import ssl context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain('certificate.crt', 'private.key')
-
NicolasZ over 3 yearsI was looking on how to implement SSL on a Dash app and this answer did the trick, here is the code:
context = ('local.crt','local.key') if __name__ == "__main__": app.run_server(host="192.168.200.100", port="8082", debug=True, ssl_context=context)
-
Mark Dominus over 3 yearsI think the API here is obsolete. My answer below gives a version of this that worked with Python 3.7.5.
-
tremendows about 3 yearswhat about SSL POODLE vulnerability?
-
Amit Tomar about 3 yearsThis really worked without much hassle of installing/configuring stuff.
-
Gabriel Schubert about 3 yearsI'm using google cloud run. In this case I only need to buy a certificate from a CA and them put it into my app following your answer?
-
Gabriel Schubert about 3 yearsI'm using google cloud run. In this case, for production, I only need to buy a certificate from a CA and them put it into my app following your answer?
-
Gabriel Schubert about 3 yearsI'm using google cloud run. In this case, for production, I only need to buy a certificate from a CA and them put it into my app following your answer?
-
RobM almost 3 yearsHey Mark how exactly did you generate those crt pem and key?
-
RobM almost 3 yearsbah forget that I see the server.crt and key we just renamed I used openssl on wsl to generate them
-
Matheus Torquato almost 3 yearsThis is running fine for me, but when I use ssl_context=context my index.html does not load the linked .css and .js local files anymore. When I run the app with ssl_context=None the html loads them with no problem. Any help here?
-
Jim JR Harris over 2 years@MatheusTorquato This is because, apparently, the default values for
ssl_context
, orssl_context = context
loads a set of restrictions that, essentially, lock down the site extremely tightly. At the site discussing Talisman as a way to secure Flask, (betterprogramming.pub/…), they say that for the usual site using SSL, this may not be necessary. Of course, that depends on your site and YMMV.