Skip to main content

UNKNOWN

Project description

* 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

1. create a "localhost CA" in ./root-ca
#+BEGIN_SRC sh
createca.sh root-ca http://localhost/crl.pem
Country Name (2 letter code) [HU]:NA
Root CA Organization Name (eg, company) []:localhost CA
Common Name (server FQDN) []:localhost
Email Address []:user@localhost
#+END_SRC
2. create https server certificate
#+BEGIN_SRC sh
servercert.sh localhost
#+END_SRC
3. Sign server cert with CA
#+BEGIN_SRC sh
cd root-ca
signcert.sh localhost
cd -
#+END_SRC
4. Setup nginx to serve
#+BEGIN_SRC sh
server {
listen 443;
ssl on;
server_name localhost;

ssl_certificate <pathto>/tlsauth/localhost.cert;
ssl_certificate_key <pathto>/tlsauth/localhost.key;
ssl_client_certificate <pathto>/tlsauth/root-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.

There's a bundled demo, to try it out:
1. set up uwsgi
#+BEGIN_SRC sh
edit flask-demo/tlsdemo_wsgi.py
#+END_SRC
2. install python dependencies
#+BEGIN_SRC sh
virtualenv --distribute env
source env/bin/activate
pip install Flask uwsgi
#+END_SRC
3. 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.
1. Create a client certificate
#+BEGIN_SRC sh
gencert.sh user
#+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.
2. CA signs users cert signing request
#+BEGIN_SRC sh
cd root-ca
signcert.sh ../user
cd ..
#+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.
3. 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
cert2pkcs12.sh user
#+END_SRC
This asks for a passphrase which is needed only once when importing into the browser.
4. 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
5. Store away user.key again together with user.cert.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.
6. 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
#+BEGIN_SRC python
# DEMO code
# 1st initialize your own CA by running from the shell:
# ./createca.sh CA

# where is our CA?
ca=CertAuthority('CA/public/root.pem', # public RSA key in PEM
'CA/private/root.pem', # public RSA key in PEM
'CA/conf/serial', # storage for a counter
'CA/dummy.pem', # a helper dummy cert for pytlsauth
'http://www.example.com/CA.crl',
# the URL to this CAs certificate revocation list
'CA/incoming', # directory to store incoming CSRs
)

# do not try this at home.
# warning: irresponsible blind trust in 3rd parties
# warning: will be ignored anyway.
# gencert('joe', 'joe@example.com', 'ACME Inc.', ca)
# even worse (and intentionally ugly)
mail(gencert('joe', 'joe@example.com', 'ACME Inc.', ca),
"Howdy.\n\n" \
"Your login certificate from %s is attached.\n\n" \
"You should import this into your browser, keep a safe\n" \
"copy and delete this mail and other copies containing it.\n\n" \
"Have fun and respect",
{'emailAddress': 'joe@example.com', 'CN': 'joe', 'O': 'ACME Inc.'},
ca.dn,
ext='p12')

# this is the correct - but less automagic - procedure
sec, pub, csr = genkeycsr('joe', 'joe@example.com', 'ACME Inc.')

# send csr to CA,
ca.submit(csr)

# who the after diligent inspection either does
cert=ca.signcsr(csr)
print cert
# or bulk processes multiple incoming CSRs
# (notice we're signing the same csr twice here, don't do this at
# home, this is only for demo purposes)
certs=ca.signincoming()
#print certs
mailsigned(certs)

# or uses the supplied signcert.sh script. Anyhow, the CA sends the
# resulting cert

# ...back to the user who after calling
pkc12(sec,cert,ca)

# imports both the result and ca._pub.
# and stores sec, cert away in a safe offline location.
#+END_SRC

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tlsauth-0.2.tar.gz (11.3 kB view hashes)

Uploaded Source

Built Distribution

tlsauth-0.2-py2.7.egg (16.0 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page