Reputation: 439
How can I authorize an API in sinatra, so that only callers possessing a known client certificate (or one issued by a trusted CA) are allowed to call it?
Currently I am using the 'thin' webserver, but I am open to other options if that is necessary.
Upvotes: 4
Views: 2141
Reputation: 37409
You can use nginx
to take care of your client-certificate - here is a blog post which shows how to set it up:
server { listen 443; ssl on; server_name example.com; ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client optional; location / { root /var/www/example.com/html; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME /var/www/example.com/lib/Request.class.php; fastcgi_param VERIFIED $ssl_client_verify; fastcgi_param DN $ssl_client_s_dn; include fastcgi_params; } }
We specify our the server's certificate (server.crt) and private key (server.key) We specify the CA cert that we used to sign our client certificates (ca.crt) We set the ssl_verify_client to optional. This tells nginx to attempt to verify to SSL certificate if provided. My API allows both authenticated and unauthenticated requests, however if you only want to allow authenticated requests, you can go ahead and set this value to on.
You can use thin
with nginx
, but I believe that using passenger
with nginx
is more popular in this case, and quite easy to deploy.
ssl_verify_client optional
is explained here:
ssl_verify_client
Syntax: ssl_verify_client on | off | optional | optional_no_ca Default: off Context: http | server Reference: ssl_verify_client
This directive enables the verification of the client identity. Parameter 'optional' checks the client identity using its certificate in case it was made available to the server.
Upvotes: 3
Reputation: 21
Since you're using Thin I don't think this is possible at the moment because peer verification appears to be broken. See https://github.com/macournoyer/thin/pull/203:
"The get_peer_cert method of EM doesn't return anything unless the cert has been verified. The --ssl-verify option of thin actually doesn't do anything. These two behaviors combined mean that env['rack.peer_cert'], which was introduced in thin 1.2.8, always returns nil. Since --ssl-verify never actually caused a verification to happen, it is better to remove that option until a fully verification process is put in place. However, the peer_cert can be made available in --ssl mode by always "verifying" the cert, thereby providing the client supplied certificate, if there is one, available in env['rack.peer_cert']."
I believe Uri Agassi is partially correct by recommending passenger but I worry a nginx/thin combination introduces a security risk if you're expecting the cert to act as the authentication if thin is ever moved off the nginx server, thereby exposing your thin server. I think an embedded appserver solution is the way to go (a la passenger).
Upvotes: 2