May 3, 2018

Recently we faced the problem how to implement a client certificate validation or so called mutual authentication with a Node.js microservice on Azure App Service. Unfortunately, the corresponding Azure documentation doesn’t provide a Node.js example for that and is kind of outdated.

This is the second post of a blog series regarding ‘Microservices with Node.js, TypeScript and Microsoft Azure’. In this series we will keep you up with different parts of this topic. (First Post / Third Post)

Motivation

There are multiple authentication methods that can be used for App Services. Mutual authentication is only one of them. The main purpose is to enforce a client to provide a certificate over TLS/SSL to authenticate. The validation of this certificate takes place on the server side. Inside of an Azure Web App we get requests from a back end that authenticates itself by a client certificate by default. Therefore we had no other option but to implement it.

How it’s not done

Normally it is possible to implement Client Certificate Validation in Node.js using the https package. Therefore one could simply add the required Client Certificate by providing an options object like that:

But unfortunately, in case of an Azure Web App this is NOT possible, because the service is not available directly from the internet. Basically a request from outside of Azure is being proxied through some components – like a load balancer for example – first. Only then it is received by the Node.js server. The Azure App Service or to be more precise the underlying IIS also terminates the SSL connections. After that it routes the request to the Node.js server without any encryption (http not https).

The Solution

As just shown, it is not an option to use the regular Node.js https approach in the service. Instead there is a way that is described on Azure docs, but as already mentioned, that is not giving details on a Node.js implementation.

As already described, Azure is terminating the SSL connection before the Node.js server gets the request. In order to forward the client certificate, it writes the certificate as base64 encoded string to the “X-ARR-ClientCert” header and adds it to the proxied request. So the Node.js / express server can validate the certificate and react according to the input. In the next sections it is shown how one can implement the validation in Node.js and how to configure Azure such that everything works.

The coding part

The key is to register a middleware that gets the “X-ARR-ClientCert” header and subsequently uses node-forge to convert the incoming base64 encoded PEM string into a certificate object. Which, in turn, can then be validated as shown in the example:

Please be aware: This is a SAMPLE verification routine. Depending on your application logic and security requirements, you should modify this method according to your needs. The code shown above, for example, does not contain a test if the certificate chains to a Trusted Root Authority, because in our use case the certificate is self signed. If you want to add this test as well, you could for example simply use the “verify” utility function that node-forge provides to you (documented here).

The configuration part

In Azure it is necessary to enable “HTTPS Only” in order to enforce SSL connections and enable “Client Certificates” to tell the IIS Server to add the “X-Arr-ClientCert” header. Otherwise the certificate will not be appended to the proxied request. This is done by changing it inside of the “SSL settings” of the App Service like shown in the picture below.

Conclusion

Now you should be able to get the client certificate from the request object and to validate the certificate according to your needs.

Leave a Comment

3 comments

  1. M

    Great Post. This might be a naive question but is it possible to validate the certificate in MS IIS somehow. We are planning a mutual auth between API management and Azure web app and do not want our azure web app to be available from anywhere else but only through the API management and hence we are looking for easy ways to implement mutual AUth

  2. Hi Mohit,

    thank you, glad to hear that. I did not try to validate the certificate in MS IIS yet, but it might be possible. There are couple of reasons why we didn’t try in our project, though:
    1. The standard way described in the azure docs were pointing out, that the IIS does not validate the certificate and will hand it over to the app (so we followed that path).
    2. I personally think, manipulating configuration of the underlying IIS (even if it might be possible), is not a good practice, if it’s not a setting provided by the web app by default.
    3. We have to provide some endpoints, that should not be secured. Therefore we validate the given certificate only when a certain endpoint gets called. Although with that solution the IIS still asks for a certificate. It is at least possible to give any certificate you want.

    All in all I want to mention that, once you have mutual authentication (client certificates) enforced, there is a lot more to think of, like using KeyVault to store the Certificates etc. Maybe it is worth to look for alternative ways of authentication/authorization within your specific use case. It could also make sense to have a look on virtual networks in Azure. Maybe this already provides the isolation you mentioned in your comment.

    Hope that helps 🙂
    Janis

  3. A

    I ran into this exact problem with my deployment yesterday. Upon finding your article it made sense as to why it was not working, since I was using the “wrong way” as you describe.

    Thanks for the article and clarification – I’m unfortunately having to recode to incorporate a solution similar to yours now.

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close