Monthly Archives: April 2013

Securing your REST API

Over the weekend, I spent several days working on integrating OAuth authentication and authorization into my FHIR server. Really, I’m primarily interested in authentication – if the user authenticates to the server, they get open access. So the functionality I implemented was that I will accept logins from any Facebook or Google user.

Integrating with Google and Facebook was almost ridiculously easy – The only thing that slowed me down was the documentation for the Google call to get a user’s profile details – I needed to provide an Application Key for charging purposes (not applicable at my volume though), and the documentation for the login process didn’t mention that (I found the solution on stack overflow).

But doing this generated some interesting discussion between the FHIR implementers preparing for the upcoming connectathon about the usefulness or otherwise of OAuth as a authentication protocol for a FHIR RESTful API. To illustrate the problem, consider this architecture, which seems like a pretty common architecture for the kind of  FHIR deployments involving OAuth:

Example fhir architecture

 

In this case, the user logs into the healthcare application – which is likely to be either a mobile or a web application, and authenticates to it using OAuth via something like Facebook, Google, etc as the OAuth server. For the user, this is convenient and observationally we know that this is really important. But, then, on their behalf, the application wants to use one or more FHIR services. How does this work? It’s pretty hard to find good information about this on the web, and the standard advice – such as this one here – really just doesn’t address this question well (at least, not that I could find).

As far as I can see, you have several options to handle this case:

  • The FHIR services – which offer the FHIR RESTful API – don’t authenticate the user. They authenticate the healthcare application, and the user is invisible to FHIR service, and vice versa
  • The FHIR services use OAuth themselves. The healthcare application asks the user to log in to each FHIR service provider independently using OAuth. 
  • The FHIR Services provide a custom login which allows the healthcare application to pass the OAuth access_token to the FHIR services – they can use this to authenticate the end-user

I find each of these unsatisfactory for different reasons.

The first option can work just fine, but the user (patient, for example) has no visibility of the data storage, and there’s no really any capacity for the user to share their own data in their own way. Whether that’s good or not depends on the context. If it’s good, then the first option is for you. And so in this case, OAuth is not appropriate on the RESTful server – just some kind of application secret

The second option has the advantage that the user is explicitly aware of the data storage, and manages that directly. They can have multiple data stores, and explicitly grant access to a particular application. That’s a different kind of use case that would work well for a few users, but would simply bamboozle the majority of users, especially those who most need healthcare and to share their data. I think that this would be a problem for the healthcare application offering. But this is the consequence of the RESTful API offering OAuth based authentication. (btw, There’s a supplementary technical problem for a web based healthcare application in this case – at the end of the authentication process, the user will get redirected away from the healthcare application to the RESTful API provider. There’s a variety of options to deal with this, but they all have problems).

The third option works well in practice, but does mean that the FHIR service provider gets the same level of access to the user as the healthcare application – and the healthcare application has to trust the FHIR service provider to impersonate it.

Tim Bray pointed out (thanks!) that there’s a 4th option if you login through Google – as part of the OAuth process, Google returns an OpenID connect JWT token, and rather than sharing the access token, the healthcare application could just pass the id_token to the FHIR Service. The FHIR service could use the id_token to verify the user identity, and that access has been granted to the application by the user. This would mean that the FHIR service has no access to any Google services associated with the user (including getting basic descriptions of the user) – it would need the access token for that. Another problem with this approach is that Facebook doesn’t generate a token like this (or any functional equivalent, so far as I could see anywhere).

Choosing to secure your RESTful api using OAuth isn’t as straightforward as it seems, then.

p.s. My server supports all 3 options from the top list – see the documentation.

 Update: Related Links

Question: Does HL7 free IP mean open?

Question

Now that the HL7 IP is free, can I just send someone I am working with a copy of the specification?

Answer

No. While the IP is now licensed as free for use, it’s not actually open. In particular, only HL7 is allowed to distribute the specifications themselves. So you’ll have to direct your trading partners to the HL7 website to get a copy for themselves.

This is really to drive membership. HL7 has a real legitimate case for driving membership – developing the standard isn’t cheap, and has to be paid for somehow. In the absence of selling the standard, rent has to be extracted from somewhere.

There is an unfortunate corollary of this though: under the current rules, no one is allowed to offer a web site or a mobile app that offers enhanced additional views of the HL7 standard (like this, this, or this, though my read of the fine print is that this is allowed. However I’m not sure about this, or this). But a mobile application that provided good views of this stuff would be greatly prized by many implementers. As you can see, there’s going to be some developments in this space, so I’ll revisit this post when that happens.

Note: the FHIR specification is not affected by all this – it remains open, and redistribution is not under any restrictions at all.

FHIR – what is interoperability?

Well, FHIR is starting to really make progress. There’s been quite a few blog posts about it recently:

Not everyone is convinced yet, but the proof of this pudding is in the eating, not academic evaluation of the source of the ingredients.

Not only is the full breadth of the specification coming together (http://hl7.org/implement/standards/fhir/resourcelist.htm), the HL7 governance & development processes are settling down, the load on my test server is going up (I can tell, I get the amazon bill!), and implementation experience is growing, with some projects going into production this year.

Which means, yes, prior to the finalization of the specification itself. In fact, that’s always been a feature of the FHIR experience: the advantages of FHIR are sufficiently compelling that projects are choosing to adopt it now, in spite of the fact that it’s not final – it’s already the best option (or is that, the least worst option?). When people talk to me about the features of FHIR that drive this, they consistently mention the following things:

  • Simplicity
  • Current technology (REST, JSON..)
  • The tooling stack that’s part of FHIR
  • Extensibility

The really intriguing item in this list is the tooling stack – one of the things people really like about FHIR is that they can (potentially) leverage the existing approaches, resources, and technology to create functionality of their own in a new space.

That actually presents a challenge to HL7. One of the goals for HL7, which is an essential part of the goals for FHIR, is “Out of the Box” interoperability. It’s a widely shared experience of HL7 implementers – two different products have made different choices about how to implement v2, so when you try to connect them up, they can’t talk to each other. Typically, rectifying this costs >$50,000 all up (including project management, vendor costs, total life cycle etc). So the HL7 community really wants different implementations to simply work together. Note that by “the HL7 community” I am describing one part of it – the part where implementers buy software from vendors to meet their business requirements.

Meeting this goal means locking down FHIR so that only HL7 can publish the engineering constructs, so that everyone can just work together. On top of this, it means good definitions, careful induction of new use cases, etc. To me, this is the classic HL7 context.

But there’s a different group of implementers at the table too. Mostly, these are institutions that perform a substantial amount of in-house development. For these developers, the ability to naturally and seamlessly leverage FHIR in other directions is very much an attraction. The fact that the solutions they develop doing this won’t interoperate with other implementations “out of the box” is completely irrelevant since they’ll never interoperate with them at all anyway.

The problem with this is that we all actually live in a continuum between the two extremes – all implementers have a mix of custom and OTS software. It’s just that the percentages differ between them, and across time as the bespoke vs commodity pendulum swings. There’s a new component to this in FHIR: external public-ish web sites (such as if, e.g. Facebook decided to put up a FHIR server linked to face book accounts for people’s own PHR – it’s not quite public, but it’s certainly not private). These will change the weighting – but not the overall picture.

I think that we are going to have to define some special conformance level. something like “Commodity FHIR”, where out of the box interoperability is an expectation, and an alternative one like “FHIR-leveraged” where interoperability out of the box isn’t assured. Is going to be messy, and it’s going to cause everyone trouble. But this mess isn’t of FHIR’s making – it’s a problem inherent in the real world.

 

Question: HL7 v2 case sensitivity

Question:

Are segments in an HL7 message case-sensitive….Example; if I change it from MSH to msh will the message still go through

Answer

Yes. Segments are case sensitive. most parsers will not accept a lowercase segment (in fact, none that i know of).

Generally, all other fixed values in the standard should also be treated as case sensitive unless you are specifically told otherwise.