Search code examples
rubysslsinatrathinclient-certificates

SSL client certificate auth with ruby (sinatra)


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.


Solution

  • 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.