Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for TLS authentication #1469

Merged
merged 2 commits into from
Sep 7, 2019

Conversation

barsand
Copy link
Contributor

@barsand barsand commented Mar 8, 2019

Continuation of PR #1188.

With this change added, one can use a dict with extra information to be added to socket creation on load_ssl_context.

Adding a more complex set of parameters to ssl_context, when using Flask, for example, will be possible through a new valid instance of ssl context, such as:

from flask import Flask
app = Flask(__name__)
ssl_context = {
		'cert_file': 'auth/server/crt.crt',
		'pkey_file': 'auth/server/key.key',
		'ca_certs': 'auth/server/ca.crt',
		'cert_reqs': ssl.CERT_REQUIRED
	}
	app.run(debug=True, ssl_context=ssl_context)

If possible - and valid, returned values from SSLSocket.getpeercert will be stored into environ['SSL_CLIENT_CERT'].

@davidism davidism added this to the 1.0 milestone Mar 8, 2019
@davidism davidism force-pushed the cert-forwarding branch 2 times, most recently from daf134c to 8008e7a Compare July 15, 2019 15:39
@davidism
Copy link
Member

davidism commented Sep 6, 2019

I'm trying to verify this, but as soon as I add ssl.CERT_REQUIRED, Firefox gives me SEC_ERROR_LIBRARY_FAILURE. Can't tell if it's a problem with my machine/Firefox, or with the way I generated the cert. I used mkcert:

$ mkcert -install
$ mkcert localhost
$ mkcert -client david
ssl_context={
    'keyfile': 'localhost-key.pem',
    'certfile': 'localhost.pem',
    'ca_certs': '/home/david/.local/share/mkcert/rootCA.pem',
    'cert_reqs': ssl.CERT_REQUIRED,
}

@davidism
Copy link
Member

davidism commented Sep 7, 2019

Must have been my computer, I tried on another and it's working as expected.

@davidism
Copy link
Member

davidism commented Sep 7, 2019

While self.connection.getpeercert() gives very nice information, it won't match what Nginx or another server could put in the SSL_CLIENT_CERT header. Nginx passes the cert in PEM format. getpeercert(binary_form=True) returns DER bytes, which can be converted to PEM. cryptography can be used to read the cert.

from cryptography import x509
from cryptography.hazmat.backends import default_backend
x509.load_pem_x509_certificate(cert.encode('ascii'), default_backend())

Also rolling back the ability to pass a dict to ssl_context. I started trying to write documentation for it and it was looking too complicated. Werkzeug already supports passing a real SSLContext object for complex stuff like this.

context = ssl.SSLContext()
context.load_cert_chain("localhost.pem", "localhost-key.pem")
context.load_verify_locations("/home/david/.local/share/mkcert/rootCA.pem")
context.verify_mode = ssl.CERT_REQUIRED

@davidism davidism merged commit dd9342b into pallets:master Sep 7, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2020
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants