Skip to main content
* tlsauth

This is a simple example how to setup TLS Certificate Authentication
for your online services. The example is based on nginx and WSGI but
should work also with an FCGI backend with PHP.

Using tlsauth you can authenticate your users based on certificates
instead of passwords. In fact you don't have to store neither the
usernames, their email addresses nor their nicks, it is all contained
in the Client certificate that is stored and presented by the
user. You can be sure, unless your signing key is compromised, noone
else can create valid certificates but you. This eliminates the need
to remember passwords and prohibits password bruteforcing. Using
nginx, you can even display totally different content depending if an
request is authenticated or not, routing unauthenticated users to
static html for example while authenticated users having access to
some dynamic content.

I don't want to scare you but this is essentially a self-signed CA, it
provides all the neccessary basic tools to make this hassle-free. Your
users only need to go through a registration procedure and then they
could enjoy seamless single-sign-on to all your services, never being
asked for a password again.

** CA and https service install
*** create a "localhost CA" in ./root-ca
#+BEGIN_SRC sh
./tlsauth.py root-ca createca http://localhost/crl.pem "Example CA" ca@example.com
#+END_SRC
*** create a "client authentication CA" in ./sub-ca
#+BEGIN_SRC sh
./tlsauth.py sub-ca createca http://localhost/client-crl.pem "hostname client CA" email@example.com root-ca
#+END_SRC
*** create https server certificate
#+BEGIN_SRC sh
./tlsauth.py root-ca newcsr localhost root@localhost >server.key
#+END_SRC
*** Sign server cert with CA
#+BEGIN_SRC sh
./tlsauth.py sign <server.key >server.pem
#+END_SRC
*** Remove Root CA private key
It is important to remove and store the root CA private key in a safe
offline location, as it can be used to mount a MITM attack against all
users, who trust this key. You need this key in 1 year, when you need
to renew your client CA certificate (per default it's only valid for
one year!)
#+BEGIN_SRC sh
mv root-ca/private/root.key <private and save location>
#+END_SRC
*** Setup nginx to serve
#+BEGIN_SRC sh
server {
listen 443;
ssl on;
server_name localhost;

ssl_certificate <pathto>/tlsauth/server.cert;
ssl_certificate_key <pathto>/tlsauth/server.key;
ssl_client_certificate <pathto>/tlsauth/sub-ca/public/root.pem;
ssl_verify_client optional;

location / {
include uwsgi_params;
uwsgi_param verified $ssl_client_verify;
uwsgi_param dn $ssl_client_s_dn;
if ( $ssl_client_verify = "SUCCESS") {
uwsgi_pass 127.0.0.1:8080;
}
try_files $uri $uri/ /index.html;
}
}
#+END_SRC
don't forget to restart nginx.

Now if users have a proper client cert installed the environment of
the WSGI application will contain the variables 'verified' and 'dn'
variables set accordingly.
** webserver Demo
There's a bundled demo, to try it out:
*** set up uwsgi
#+BEGIN_SRC sh
edit flask-demo/tlsdemo_wsgi.py
#+END_SRC
*** install python dependencies
#+BEGIN_SRC sh
virtualenv --distribute env
source env/bin/activate
pip install Flask uwsgi
#+END_SRC
*** run flask application
#+BEGIN_SRC sh
basedir=$PWD
env/bin/uwsgi --socket 127.0.0.1:8080 --chdir $basedir/flask-demo -pp $basedir -w tlsdemo_wsgi -p 1 --virtualenv $basedir/env
#+END_SRC
** Client side setup
How to create a proper Client certificate.
*** Create a client certificate
#+BEGIN_SRC sh
./tlsauth.py root-ca newcsr joe joe@localhost >joe.key
#+END_SRC
send the resulting "user.csr" to the CA for signing. In this case
you are both, but in a normal case this step is done by arbitrary
users who send this csr file during the registration process to the
site.

Store user.key away somewhere safe offline, you'll need it later
once more.
*** CA signs users cert signing request
#+BEGIN_SRC sh
./tlsauth.py root-ca sign <joe.key >joe.cert
#+END_SRC
CA sends back the signed 'user.cert" to the sender. As a
convenience feature also the root CA cert should be sent to the
user, so he can import this also in his CA store.
*** Create PKCS#12 cert for your browser
Using the returned cert from the CA we convert it together with the
secret key part to a PKCS#12
#+BEGIN_SRC sh
./tlsauth.py root-ca p12 joe.key <joe.cert >joe.p12
#+END_SRC
This asks for a passphrase which is needed only once when importing
into the browser.
*** Import the certificates in Firefox
1. Using the menu open the Preferences dialog.
2. Select the Advanced toolbar icon
3. click on the "View certificates" button
4. On the "Authorities" tab click on the Import button and import
the root CA cert (this must be supplied by the CA to you).
5. on the "Your Certificates" tab click on the "Import" button and
load the file "user.cert.p12"

if everything went ok the new certificate should appear under the
"Your Certificates" tab
*** Securing keys
Store away private key in joe.key again together with the pkcs12
cert joe.p12 in a safe offline location (maybe your backup?), if
you reinstall your browser you want to import user.cert.p12 back
into it again.

If you now surf to https://localhost with this firefox, the flask
application should report back your distinguished name. If you
browse to this location with another browser which lacks this
certificate you will probably see the default nginx installation
html page.
** Python usage
see test.py
** Changes
*** v0.4
Fixed dangerously exposed Root CA key, by introducing a sub CA
only for signing the client authentication keys, and thus
eliminating the chance for a MITM attack in case the Root CA gets
compromised.

Metadata

Release files for tlsauth 0.4-1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tlsauth 0.4-1
File Size Uploaded Provenance
tlsauth-0.4-1.tar.gz 12.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tlsauth 0.4-1
File Interpreter ABI Platform
tlsauth-0.4_1-py2.7.egg Legacy Egg format - - Details

Total release size: 29.9 kB

Release files / tlsauth-0.4-1.tar.gz

Download URL tlsauth-0.4-1.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
36b26b5ba5d0ff1b38c6863b9b487b0acba30e77e4c465a4742ed0a29c9afc76
BLAKE2b-256 checksum
How to use checksums
2c34430c1acc2fc810329979853f0c64841e20d078472fb9111f7068504aa179
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / tlsauth-0.4_1-py2.7.egg

Download URL tlsauth-0.4_1-py2.7.egg
Size 17.6 kB
Tags Egg
SHA-256 checksum
How to use checksums
8a73c8ad70e66a1f5dc682159d867b6e46242b6edc5410c68edf0dcdf8cb615e
BLAKE2b-256 checksum
How to use checksums
bdb3a2d4c87eae12c5dad0410afead99cb16c481b2e753758936782111fb5268
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for tlsauth 0.4-1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page