How to authenticate https client certificates using Dancer/Starman or Mojolicious/Daemon?

490 Views Asked by At

I am trying to perform Authentication using HTTPS client certificates using perl Dancer framework. I would like to accept requests sent with/without certificate and do validation on the certificate CN to proceed with the valid response (https://medium.com/@sevcsik/authentication-using-https-client-certificates-3c9d270e8326, the link shows how to do it in node.js, need something very similar for perl Dancer/Starman/Plackup)

I have setup ssl using Dancer/Plackup, but have not found a way to get details about the peer certificate to perform validation in Dancer framework

I would like to achieve the following:

If the request is sent

without certificate => 401

with certificate but client has self-signed (CN doesn't match with server cert CN) => 401

with certificate but client cert has been signed using server cert (CN matches server cert CN) => 200

2

There are 2 best solutions below

1
daxim On

In Dancer you can get the IO::Socket::SSL object with request->env->{'psgix.io'}, but that does not help you because you have no opportunity to configure it for client verification. IO::Socket::SSL::set_defaults does not run early enough, either.

This means it's best to set up Apache httpd or nginx to terminate TLS. Pass on the certificate info you need (e.g. client verification result) in environment variables to the Dancer application.

0
Manoj Sagar On

To anyone who is facing the issue, I solved it by the following steps: (To create client and server certificates, I followed https://medium.com/@sevcsik/authentication-using-https-client-certificates-3c9d270e8326)

1) Use nginx (Setup guide:https://gist.github.com/netpoetica/5879685)

2) Create the nginx config

server {
    listen 443 ssl;
    server_name localhost;
    ssl_certificate /to/path/server_cert.pem;  # server certificate
    ssl_certificate_key /to/path/server_key.pem; # server key

    ssl_client_certificate /to/path/server_cert.pem; # client CA => server certificate for self signed 
    ssl_verify_client on;

    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header SSL_CLIENT_CERT $ssl_client_cert; #ENTIRE CLIENT CERTIFICATE
        proxy_set_header SSL_CLIENT_S_DN $ssl_client_s_dn; #SUBJECT DN
        proxy_set_header SSL_CLIENT_I_DN $ssl_client_i_dn; #ISSUER DN
    }
}

More details regarding ssl can be shared using the attributes mentioned on http://nginx.org/en/docs/http/ngx_http_ssl_module.html#variables

3) Dancer application

get '/' => sub {
    info to_dumper(request->headers);
    content_type 'text/xml';
    return "OK";
};

4) Start the dancer application using plackup (or starman/your preferred choice)

carton exec plackup -R /bin,/lib bin/app.psgi

5) Send the request to the server

curl -v https://localhost/ --key client_key.pem --cert client_cert.pem --cacert server_cert.pem

6) You should observe client certificate details in the plackup logs