I am developing a RESTful web service with Bottle, probably soon to migrate to Werkzeug. I’d like to implement an auth scheme that works based on a private/public key pair where the server only has to store the public part while the user keeps the private one. Upon access, the server would require the accessor to perform an action using the private key that the server can verify and relate to the public key part. Upon success, for example a token is generated which can be used for some time. What is the path to implement something like this for Werkzeug or Bottle? Any projects/examples i could work from?
Share
I believe, the best option here is to shift the responsibility to work with cryptography onto something else. Web servers and CA (certification authorities) are good with it.
Basically, altogether they can
We use such mechanism to authenticate a third-party payment service (sorry, private code), and there is also a plugin to Redmine providing the same mechanism of client authorization, and we use it too (certainly, it’s Ruby, but it’s also a valid proof that such services can be found in wild.)
To make things work, all you need is to
Below is an tiny example with easyrsa, nginx, uWsgi and werkzeug
Configure CA
The easyrsa toolkit is a part of OpenVPN installation. It’s possible to use OpenSSL “raw” command or PyOpenSSL, but easyrsa is convenient and suitable at least at the concept stage.
Create CA
Create server certificate
Create client certificate.
In the sample above you create both client secret key and its corresponding public part (certificate), but good practice assumes that you sign client certificate requests instead, and has no access to secret part.
Some services generate a pair of secret key + certificate for you and then write a message on download page like “this is the only chance for you to download the secret key. We don’t store it, so it cannot be download later.”
Additionally, this command creates a PKCS12 file with encrypted key and certificate, which is handy for import to browsers.
Configure nginx
First, we should create a pair “server certificate + ca certificate”, as our CA self-signed:
Then the following config can be applied:
More information on configuration options is available here and here.
Ensure you have correct privileges to the /etc/nginx/easyrsa directory and only root and nginx can get access to secret keys.
Write a Werkzeug application
The python part is trivial. Just read the variable SSL_CLIENT_ID from WSGI environment.
The contents of the sample application in file
sample.pyLaunch the service with a uwsgi server:
uwsgi -w sample:application --socket 127.0.0.1:5000Test your installation
It’s easy to test with curl