Set up Mutual SSL Authentication for Local Development

April 05, 2021

Tags: Programming

Working with clients in the healthcare industry sometimes requires us to interface with electronic medical records (EMRs). These systems are responsible for collecting patient medical data throughout the care process and often contain data critical to an app we’re building. Fortunately, EMRs typically have some sort of API that we can interface with to get the information we need.

EMR APIs can transmit private health information, so I’m sure you can imagine that the developers of these systems tend to be quite serious about security. For a recent client project, I had to work with the web API for a cloud-based EMR, PointClickCare. It was a bit tricky to get set up for local development, but I eventually got everything working. Noticing that these roadblocks were common for developers, the PointClickCare team asked me to write a guest blog post documenting my experience, which follows.


Originally published : https://developer.pointclickcare.com/spa/blog/set-up-mutual-ssl-authentication-for-local-amplify-development

Overview

SSL. Secure Sockets Layer. It’s the “S” in HTTPS, and a technology that you, as a web developer, are almost certainly familiar with in some capacity.

It could be that you deal with SSL strictly from a client perspective, pointing your SSL-compatible web browser at one of the secure web pages that, according to some metrics, account for over 80% of pages loaded.

Or maybe you’ve found yourself on the other end of the equation, configuring your web server to respond to SSL requests with a valid certificate, thus assuring clients that they are communicating with a known entity over a secure channel.

We act as clients (and sometimes servers) all the time as part of our work, but far less commonly do we find ourselves acting as both simultaneously. However, that’s just what’s required of us working with the PointClickCare REST API.

The PointClickCare API implements a mutual, or two-way, authentication strategy. This means that, in addition to sending you an identity-validating certificate as part of the SSL handshake, you are required to send one back. This ensures not only that you can trust PointClickCare, but that PointClickCare can trust you, which is important when dealing with Protected Health Information.

Mutual authentication naturally requires a little extra leg work on your part—namely sending a known-good certificate over the wire as part of your API requests. This ends up being fairly straightforward when you are sending requests from a server already provisioned with an SSL certificate, but can make local development a bit cumbersome.

In this guide I’ll explain how to configure the PointClickCare developer platform and your local development environment to participate in two-way SSL transactions so you can focus on building apps.

A quick note about terminology

Some of the underlying technology described here may actually be using SSL’s successor, Transport Layer Security (TLS). It’s common to see these terms referred to collectively as “SSL/TLS” or simply “SSL” when talking about secure HTTP at a high level. As the distinction isn’t important in regards to what this guide will cover, I’ll simply use “SSL”.

The game plan

Our undertaking is comprised of five basic steps:

  1. Spin up a local web server
  2. Create a public tunnel from our server to the Internet at large
  3. Generate an SSL certificate for the tunnel domain
  4. Configure our PointClickCare app to expect our certificate as part of the SSL handshake
  5. Test our work

We’ll be using the following tools in this guide, so they should be considered prerequisites:

All of these tools are available for macOS, Windows, Linux, and FreeBSD.

If you intend to follow along with the guide explicitly, two assumptions are made:

  • You’re using macOS
  • You have Homebrew installed

That being said, the concepts presented herein should be able to be easily extrapolated to suit other tools and operating systems.

The server

The first thing we’ll need is a locally-running web server. nginx is a fast, easily-configured option, so let’s install that:

$ brew install nginx

Don’t start the server yet, as we need to make a quick configuration change.

By default, nginx listens on port 8080, but Certbot’s challenge strategy runs against port 80. To configure nginx to listen on port 80 instead, we need to edit its configuration file; if you installed nginx via Homebrew (as shown above), this file should be located at /usr/local/etc/nginx.conf.

Find the line listen 8080; in the nginx config file, and change 8080 to 80. The line should be just over 30 lines from the top, in a server block:

    server {
        listen       8080; # <-- Change 8080 to 80
        server_name  localhost;

To start the server, run brew services start nginx. If you visit http://localhost:80 (or simply http://localhost/) in a web browser and see the default “Welcome to nginx!” page, you’re good to go.

The tunnel

In order to obtain an SSL certificate, we need our web server to be accessible on the Internet at an actual domain name (not just an IP address). You could acquire or reuse a TLD, obtain a static IP address, set up port forwarding on your router, configure DNS records et al., but thankfully there is a much simpler path: ngrok.

ngrok describes itself as ”One command for an instant, secure URL to your localhost server through any NAT or firewall.” Great! Let’s install it.

$ brew install --cask ngrok

ngrok offers free and paid plans that enable all sorts of interesting features, but for our use case we can use it anonymously, straight out of the box.

We need to tell ngrok that we want to accept HTTP traffic on our local nginx port (80), so we’ll run the following command:

$ ngrok http 80

Look for the “Forwarding” details in the output from the command—these are the URLs at which your ngrok tunnel is available. The domain name should look something like b93670bc0192.ngrok.io. If you visit either URL in your browser, you should see the nginx welcome page. Neat.

The certificate

The last bit of work on our end is to obtain an SSL certificate for our ngrok domain. The lovely folks over at Let’s Encrypt offer free certificates, so we’ll go that route.

Certbot is an easy-to-use CLI that can help you obtain a Let’s Encrypt cert. Let’s install it:

$ brew install certbot

Now it’s just a matter of obtaining the certificate:

sudo certbot certonly --standalone -d b93670bc0192.ngrok.io

A few notes about this command:

  • The standalone flag tells Certbot to spin up a temporary web server to complete the SSL challenge.
  • The d option allows us specify the domain for which we want a certificate (this should correspond to your ngrok tunnel domain).

If all goes well, you should see an “IMPORTANT NOTES” section in the command output. This section will detail where the newly-obtained certificate and private key are; the purpose of the latter is beyond the scope of this guide, but you can read more about public-key cryptography on Wikipedia if you’re interested.

Make note of the location of these files. By default they should be:

  • /etc/letsencrypt/live/b93670bc0192.ngrok.io/fullchain.pem
  • /etc/letsencrypt/live/b93670bc0192.ngrok.io/privkey.pem

If you inspect those files, you’ll see that they’re actually symbolic links to files in /etc/letsencrypt/archive/b93670bc0192.ngrok.io, which are owned by the root user. Let’s make them a bit more convenient to work with:

$ mkdir ~/certs
$ sudo cp -R etc/letsencrypt/archive/b93670bc0192.ngrok.io \
		~/certs
$ chown -R alice ~/certs/b93670bc0192.ngrok.io

Be sure to replace alice with your username.

PointClickCare configuration

We’re now ready to use our certificate/private key to make requests to PointClickCare. At this point, though, you might be wondering how PointClickCare will know what certificate to expect. The answer is, we need to specify, in our app settings, the Common Name (CN) that our certificate is associated with.

To determine the CN, you can open the fullchain.pem file with Keychain Access, but spoiler-alert—in this case, it’s just the domain name. So, the CN for the certificate in this example would be “b93670bc0192.ngrok.io”. Convenient.

Head over to the My Apps page in the PointClickCare dashboard, select your app, click “Edit”, and look for the “Certificate Common Name” field. Enter your certificate’s CN and you’re good to go.

Trial run

At this point, you should be ready to make mutually authenticated requests! There are myriad ways to do this, and what you use will be specific to your technology stack, but I’ll go over a couple of universal examples that I tend to use when developing against the PointClickCare API.

curl

Our good friend curl allows us to easily make two-way SSL requests by specifying the certificate and private key files.

First get an access token:

$ curl https://connect2.pointclickcare.com/auth/token \
	-H "Authorization: Basic $BASIC_AUTH" \
	--cert ~/certs/b93670bc0192.ngrok.io/fullchain.pem \
	--key ~/certs/b93670bc0192.ngrok.io/privkey.pem

To learn more about getting an access token, check the documentation. Now use that access token to make an API request.

$ curl https://connect2.pointclickcare.com/api/public/preview1/orgs/$ORG_UUID/facs \
	-H "Authorization: Bearer $ACCESS_TOKEN" \
	--cert ~/certs/b93670bc0192.ngrok.io/fullchain.pem \
	--key ~/certs/b93670bc0192.ngrok.io/privkey.pem

Success (hopefully)!

Postman

Postman is a handy tool for working with web APIs, and includes support for mutual SSL authentication.

To set this up, open the Settings modal (Postman → Preferences) and click “Certificates”. Click “Add Certificate” and enter “connect2.pointclickcare.com” as the “Host”. Select your fullchain.pem for “CRT file” and your privkey.pem for “KEY file”.

Now any outgoing requests to connect2.pointclickcare.com from Postman will include the certificate and private key. Nice.

Outro

Hopefully you find this guide useful in getting started developing apps that integrate with PointClickCare. If you have any questions, I’m on the PointClickCare developer forum as ngscheurich. Good luck!

Nicholas Scheurich

Senior Developer

Scholar of arcane mysteries such as computer programming, game design, and the Vim text editor. Feed your Nick one cortado each morning to maintain its shiny coat and joie de vivre. he/him

let's talk.

Together we can make something great.

contact us about new work

Contact

225-407-4520

hello@newaperio.com

Social Media