Application Programming Interfaces (APIs), particularly those that expose Personal Health Information (PHI) have security issues to consider. Substitutable Medical Applications and Reusable Technologies (SMART) is a healthcare standard, that adds a layer of security in front of FHIR interfaces to support safe access to data held within an Electronic Health Record (EHR) – or any other repository.
Recently I gave a webinar in SMART for HL7® and one of the comments I received was there was not enough detail to allow a developer to implement it. This was not the main focus of the event, but it did make me realize that there a lot of interest about SMART from developers and how could this need be met. In the next year, we’re planning on ramping up FHIR implementations in New Zealand, and we need to start with security up front – rather than something that gets thought about once an app or an API has been developed.
The SMART specification
The SMART specification is very readable – but this is a complicated topic, and having different descriptions and perspectives is always helpful.
To help developers out, I’m developing both a SMART client and server and I will use these in a series of posts to call out the key parts of the ‘OAuth handshake’ that occurs when a client authenticates to a server in sufficient detail for a developer. The focus will be on how SMART is used to protect APIs, where the API is a source of data that can be provided in a secure, controlled fashion to an external party.
If you’ve heard of SMART, it’s likely in the context of supporting ‘app launches’ – the ability to have separate ‘mini-apps’ that can be launched from an Electronic Health Record (EHR) to perform a specialized function. This is then able to identify itself to the EHR and access data from its database via FHIR APIs. There are 2 ‘launch types’ defined:
The ‘EHR launch’ where an EHR user launches the app in the context of a patient or an encounter. In this scenario, the app is effectively extending the functionality of the EHR. Note that the term Electronic Medical Record (EMR) is often used as well.
The ‘standalone’ launch where the app is started externally to the EHR but is able to securely connect to the EHR and access this data.
It’s the standalone pattern that I’m going to be focusing on, as – really – this is just an application accessing data through an external API.
In describing SMART in the past, I’ve generally described how the authentication process works starting with the app being launched, connecting to the API and the subsequent workflow steps that occur. However, an alternative way of thinking about this is to view it from the perspective of the API.
Suppose you’re an EHR or shared repository exposing data you have through an API. One of the key things you’re going to be interested in is who is making the call – and are they allowed to access the data you’re providing. You’ve got a couple of ways of managing this. You could do it all yourself – establishing a way to identify the caller and figure out what data they are allowed to access and what operations they are allowed to do – read, write, update, delete.
Or, you could offload that task to someone else and focus on the ‘business’ side of providing access to data. You’d want some way for each caller to be able to prove that they have been validated by the other service. They would have to provide a ‘token’ of some sort that you could check before allowing them access to the data – in a similar way to a passport that proves to a customs agent that you are who you say you are.
This is how OAuth2 (and therefore SMART) works – as SMART is a way of using OAuth2. The system providing the API is called the ‘Resource Server’, and the system checking the caller is called the ‘Authorization Server’. Note that they don’t have to be completely separate systems, they can just be specialized modules within the same application. Also, the exact way that the 2 systems interact is not defined in the specification – that’s up to the individual implementation. For example, when the Resource Server receives a request for data, there will be a token of some sort that was supplied by the Authorization Server. This token could itself contain the identification of the user and their permissions in some encrypted fashion that the Resource Server can examine directly. Or it could simply be a unique ‘key’, and the Resource Server uses it to check with the Authorization Server on each request.
We’ll talk more about this in later posts.
There are 2 other actors in this picture to think about, and they are on the caller side.
There is the actual application that is making the call, and also the user of that application. For example, suppose I am the developer of a Consumer Portal and I want to access data from the consumers EHR (maybe their Primary Care system) or from a repository of other data like laboratory results.
From the perspective of the EHR providing the API, they are quite different things, and it would want to be able to identify both of them when deciding whether or not to allow a specific call to proceed.
Incidentally, the user of the app making the call is called the ’Resource Owner’ in OAuth2 – reflecting the common use of AOuth2 to allow a person to use a separate app to access data that they provided to the resource server – think of a mobile app accessing Twitter or Facebook data for example.
So, we have a total of 4 different actors to think about:
A user (person) who is using an app that needs to access data from somewhere else.
An application that the user is using to do so.
The system that has the data being exposed through the API – the Resource Server.
The system that is responsible for checking the app and the user of that application – the Authorization Server.
And the overall flow of the interaction is something like this:
The user invokes a function in the app that requires it to get data from the API.
The app connects to the Authorization Server and validates both itself and the user. (This is important – both are checked). The Authorization Server returns a token (called an Access Token) that the app can include in a subsequent call to the Resource Server as proof that it is allowed to call the API.
The app makes the API call, including the access token. The Resource Server checks that the access token is valid, and that the app/user is allowed to access the data they are requesting, and if so, will process the API call.
Of course, the details are a bit more complex than that – but fundamentally this is how it works.
We’ll dive into those details in later posts.
To learn more about why SMART on FHIR is smart, read my white paper which reviews SMART, and considers how an organization can support and benefit from this healthcare standard.