Client-side OAuth2 support with Google's OAuth Client for Java library

270 views
Skip to first unread message

Matt Clarke

unread,
Jun 20, 2016, 2:52:16 AM6/20/16
to HAPI FHIR
Hi there,

I'm working on an Android client with HAPI-FHIR for talking to a FHIR server and using OAuth2 for authentication.

Rather than rolling our own Oauth2 implementation, we're currently making of use Google's OAuth client library to handle initial token fetching (password grant), and then using HAPI's BearerTokenAuthInterceptor to sign requests with the access token:

val client = fhirContext.newRestfulGenericClient(serverBase)
client.registerInterceptor(BearerTokenAuthInterceptor(accessToken))

This is nice and simple, but a bit more is needed to handle refreshing the access token if it's about the expire or if the server returns the relevant error response. Google's Oauth library can handle all of this automatically... but only if you use Google's HTTP client to make requests. E.g. from the library docs:

public static HttpResponse executeGet(
     
HttpTransport transport, JsonFactory jsonFactory, String accessToken, GenericUrl url)
     
throws IOException {
   
Credential credential =
       
new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accessToken);
   
HttpRequestFactory requestFactory = transport.createRequestFactory(credential);
   
return requestFactory.buildGetRequest(url).execute();
 
}

So in order to work with HAPI, what I've done currently is to reimplement Google's expiry logic prior to making FHIR requests, and delegate to the library to refresh the token if needed (any needed calls will use Google HTTP client). Then once there's a valid access token, only then does it proceed to creating an (Apache) HAPI restful client to make FHIR requests.

This out-of-band handling of authorisation logic has a smell to it; it seems like it would be architecturally better to have a restful client that played nice with HAPI to handle these low-level details. 

There's also the issue of having two different HTTP clients (Google's and Apache), which means both app binary and memory bloat, as well as double-handling for SSL config, etc.

So my question is, is there a RestfulClientFactory implementation out there that already handles client OAuth2 scenarios like this nicely? And if not, could it be worth writing and releasing a Google HTTP client plugin for HAPI to support this? I'm interested in hearing if this would be a worthwhile development effort. 
Or some third option, perhaps handling OAuth2 prior to moving control to HAPI classes isn't actually so bad :) 

Cheers, Matt






James Agnew

unread,
Jun 20, 2016, 10:03:04 AM6/20/16
to Matt Clarke, HAPI FHIR
Hi Matt,

First let me preface this with the fact that I am not much of an Android dev- I don't have a complete answer to this, just some thoughts to jot down. :)

One of the things that is overdue on the Android side of HAPI is to get rid of our dependence on Apache HttpClient entirely. Using it made some sense when we started the project, but given that Android has basically completely disowned that library at this point it seems like it would make way more sense for the Android version of HAPI to just use URLConnection like Google recommends.

This would have been a big headache up until recently, but after a bunch of awesome work from the Agfa team HAPI gained the ability to support multiple client backends. They did it in order to replace HttpClient with Jersey in their implementation, but one of the things we discussed as they were designing it was the ability to plug in URLConnection on Android at some point too.

While I'm talking about roadmap stuff for Android, the other thing I see as a short/medium term goal is to replace our use of javax.json/JSR353 with GSON. JSR353 was another choice that made sense when we started HAPI but it seems like that proposal has been abandoned so it doesn't make much sense to continue with it. I figure by the time we have moved to GSON, made the use of XML optional, and created a URLConnection based backend it should be possible to use HAPI on Android without any of the "special uberjar for android" nonsense that is currently required.

In terms of the Google HttpClient, I may be wrong, but isn't that library just a thin wrapper around arbitrary http client libraries (not unlike RestfulClientFactory in some ways)? I would assume that whatever client implementation you're using (including the current Apache one) it should be possible to plug that into Google HttpClient without introducing much extra bloat. This could be misunderstanding on my part though- I've never used the Google library.

I'm not aware of any existing RestfulClientFactory implementations that handle what you described. At least if anyone has written one they haven't let us know about it :) This sounds like a very useful thing though.. although I have no idea what would be an easier way to do it. It probably wouldn't be hard to create a RestfulClientFactory that is backed by Google's client. Alternately, adding the appropriate hooks into RestfulClientFactory might be an option too. I'd guess the latter would be more work, but might be more flexible down the road?

Looking forward to seeing how this progresses... Naturally if you think your work would be useful to others too, we'd certainly welcome it as a contribution to the core library. :)

Cheers,
James



--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+...@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/c05a7444-c7c6-420f-bd03-2916ace7244f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Matt Clarke

unread,
Jun 22, 2016, 7:17:55 PM6/22/16
to HAPI FHIR, kiwiand...@gmail.com
Hi James,

This is very interesting as an Android developer using HAPI-FHIR, thanks for the reply. Yes my mistake, you're completely right about Google's HTTP client. Looks like it even offers an Apache HTTP Transport out-of-the-box which should take care of the issues with having 2 HTTP clients. Nice :)

> One of the things that is overdue on the Android side of HAPI is to get rid of our dependence on Apache HttpClient entirely.

This would be awesome :) It's interesting to hear about Agfa's work abstracting away the HTTP client in HAPI. Square offers a nice alternative HTTP client called OkHttp and is used by HttpURLConnection's implementation in Android 4.4+. I don't know if this could make sense as an alternate Android-friendly HTTP client implentation for HAPI too, it's something I'd be really keen on exploring.

> Alternately, adding the appropriate hooks into RestfulClientFactory might be an option too. I'd guess the latter would be more work, but might be more flexible down the road?

This sounds cool. I'm not sure I completely follow, do you mean adding (authorization related?) hooks that can be made use of by any OAuth2 library rather than tightly coupling Oauth2 support to Google's library? This seems like a better idea, could you elaborate?

Cheers,
Matt
Reply all
Reply to author
Forward
0 new messages