Apache and forwarding a client certificate Id to WebSocket

Recently I came across a problem of forwarding a certificate Id to backend service for the authentication purposes. I also do not want to handle SSL at services.

Let’s say I have a server setup as follows: There is an Angular website on port 4200 and REST/Websocket services on port 3000. REST services are accessible over endpoint /kumuluz and Websocket connections via /v1/devices. As a common facade to access these services I set up Apache as a reverse proxy as in an example configuration below.

To extract a field from a client certificate (e.g. CN in my case) and forward request to a backend REST server with an additional header field is not a problem. I just extract property %{SSL_CLIENT_S_DN_CN}s and set a header field clientId.

The problem comes, when you would like to do the same for the Websocket connections – you cannot set header for these type of connections. But you can do a workaround (the point of this post): Tell clients to connect to the endpoint /v1/devices/CLIENT_ID and then check if the parameter matches the client id of underlying client certificate. Now you forced the client to use the correct ids in URL, which you can use for authentication as Apache forwards only requests where SSLRequire successes.


<VirtualHost *:80>
   ServerName portal.zitnik.si
   Redirect permanent / https://portal.zitnik.si/
</VirtualHost>

<VirtualHost *:443>
        ServerAdmin slavko@zitnik.si
        ServerName portal.zitnik.si
        ServerAlias portal.zitnik.si

        DocumentRoot /var/www

        ProxyPreserveHost On
        ProxyRequests Off

        ProxyPass /images !
        
        ProxyPass /v1/devices ws://localhost:3000/v1/devices
        ProxyPassReverse /v1/devices ws://localhost:3000/v1/devices

        ProxyPass /kumuluz http://localhost:3000
        ProxyPassReverse /kumuluz http://localhost:3000

        ProxyPass / http://localhost:4200/
        ProxyPassReverse / http://localhost:4200/

        RedirectMatch ^/$ https://portal.zitnik.si

        SSLEngine on
        SSLCertificateFile /home/slavkoz/certs/portal.zitnik.si.crt
        SSLCertificateKeyFile /home/slavkoz/certs/portal.zitnik.si.key

        SSLCACertificateFile /home/slavkoz/certs/CA.pem
        SSLVerifyClient none
        RequestHeader set clientId ""

        <Location /kumuluz/software>
                SSLVerifyClient require
                SSLVerifyDepth 1

                RequestHeader set clientId "%{SSL_CLIENT_S_DN_CN}s"
        </Location>

        <Location /v1/devices>
                SSLVerifyClient require
                SSLVerifyDepth 1

                SetEnvIf Request_URI "/v1/devices/(.*)$" CLIENT_ID=$1
                SSLRequire       %{SSL_CLIENT_S_DN_CN}  eq %{ENV:CLIENT_ID}
        </Location>
</VirtualHost>

Leave a Reply

Your email address will not be published. Required fields are marked *