HTTP Basic Authentication using client SSL certificate's CN

Suppose you have a HTTP service which is able to authenticate users only using Basic HTTP Authentication. On the other side every your client (a real user or a 3dparty system) has its own client SSL certificate and you want them to authenticate using the certificates' CNs.

haproxy is to the rescue!

Offtopic:
If you are not familiar with haproxy, but working in web-services engineering, it is worth at least to look at it. It is quite handy tool which could be used in very surprising ways. Just have a look at http://www.haproxy.org/

Here is the chunk of the haproxy configuration, which get things done.

frontend fe1
        mode http
        bind *:15672 ssl crt server.pem ca-file trusted_ca.pem verify required
        http-request set-header X-Tmp          %[ssl_c_s_dn(CN)]:password
        http-request set-header Authorization  Basic\ %[hdr(x-tmp),base64]
        http-request del-header X-Tmp
        default_backend be1

backend be1
        mode http
        server server1 127.0.0.1:15673 maxconn 1024

What does this piece of configuration exactly do?

It declares publicly accessible HTTPS service on port 15672. The user should connect only with a valid client SSL certificate, which MUST be validable against certificates located in trusted_ca.pem file.

If the authentication is OK, it creates valid "Authentication" header based on the CN provided by client SSL certificate and default password "password". That Authentication header is passed to backend listening on 127.0.0.1:15673. The backend then can validate the user using basic authentication mechanism.

Of course, the backend should known about the user with password "password".

Don't be scared that everybody knows the password. Since the frontend always rewrites Authorization header with the data, provided by the SSL subsystem, it is impossible to impersonate to particular user. So the password here is needed just to comply with backend authentication protocol.

No comments: