FHIR Chat · Dynamic URL Port · smart

Stream: smart

Topic: Dynamic URL Port


view this post on Zulip Gino Canessa (Nov 02 2020 at 18:36):

Question for server implementers: I was going through the app launch sequence with local redirect, and there is a note in the registration section about using dynamic ports for native apps (described in RFC 8252 - Loopback Interface Redirection).

Have servers implemented this? If not, what is the expected strategy?

view this post on Zulip Isaac Vetter (Nov 11 2020 at 19:47):

Gino - sorry for the delayed response. We have not implemented this.

view this post on Zulip Gino Canessa (Nov 11 2020 at 19:57):

No worries, thanks for replying!

I figured as much, though it is disappointing. It is frustratingly complex for cross-platform applications (e.g., desktop apps for Windows, Linux, and MacOS).

view this post on Zulip Isaac Vetter (Nov 12 2020 at 15:16):

Gino, I started re-reading Window's app URI handlers to determine if they accommodated your need and then realized that you're trying to use a localhost redirect url with a dynamic port, which is pretty different from the app URI handler solution, right? In your case, are you developing a desktop app or a web app running on localhost? If the first, does the app URI handler solution meet your needs? If not, mind educating me?

view this post on Zulip Gino Canessa (Nov 12 2020 at 16:44):

Thanks for looking more into this Isaac! The page you linked to has a simplified process for UWP apps, but does not work for any other types of applications. In my case, I'm starting from the perspective of a cross-platform .Net Core application.

In order to register a protocol handler, you need to jump through platform-specific hoops for each OS. Windows, for example, requires registry modification (which may need elevated permissions) for non-UWP apps. Linux and MacOS are similarly complicated.

Adding an http server to a .Net Core app is a package and a few lines of code (maybe 100-ish, mostly boilerplate). This works across all desktop platforms out of the box. The issue with a local server is that if another application has already grabbed the port you registered, you can't get it. Since it's a common problem, the http server supports dynamic port registration as well... but that means the redirect URI needs to have support for it.

view this post on Zulip Jenni Syed (Nov 12 2020 at 18:33):

I would actually recommend using an app claimed URL if you can... but I know that's not available on all platforms :( There have been vulnerabilities created with the localhost approach before... most recent one that got a lot of attention was Zoom.

view this post on Zulip Jenni Syed (Nov 12 2020 at 18:33):

We actually don't currently allow "localhost" to be registered in our production environment today

view this post on Zulip Gino Canessa (Nov 12 2020 at 18:45):

The RFC only allows for 127.0.0.1 as the base (both to mitigate name-resolution vulnerabilities and to prevent external traffic from hitting the port). .Net Core actually enforces this for dynamic registration as well (e.g., I can ask for a dynamic port on 127.0.0.1, but not localhost).

view this post on Zulip Jenni Syed (Nov 12 2020 at 18:48):

Yes, the method I'm talking about is section 7.2 in native rather than the loopback method (section 7.3)

view this post on Zulip Jenni Syed (Nov 12 2020 at 18:49):

Which is also the "preferred" method called out in that spec

view this post on Zulip Gino Canessa (Nov 12 2020 at 19:01):

Thanks, seeing if there's a good cross-platform option for that process now. That said, if nobody supports (or even plans on supporting) local dynamic port registration, I don't think we should specifically call it out in the spec.

view this post on Zulip Gino Canessa (Nov 12 2020 at 19:15):

Hmm.. as far as I can tell, that does not work from .Net Core either (the client configuration page calls out that .Net Core needs to use localhost for OAuth redirection).

I'm sure I can sort out a workaround, but it goes back to the same process as the protocol handlers - relatively complex OS-specific code. Not impossible, but definitely annoying.

view this post on Zulip Jenni Syed (Nov 12 2020 at 19:36):

Many of our native windows apps have used the first option (custom scheme)...

view this post on Zulip Jenni Syed (Nov 12 2020 at 20:10):

@Gino Canessa another challenge with that and specifically with SMART is that you can't launch against a dynamic port... so you would need to figure out that challenge. Only standalone apps really have a chance in heck on using that, but I agree that if nobody supports it we may need to push back

view this post on Zulip Gino Canessa (Nov 12 2020 at 20:10):

Yep - custom scheme is easy (app config) in Windows UWP apps. It's straightforward (if not ideal - registry changes, possible permissions issues) in other Windows-only apps. Without local redirection, cross platform apps (e.g., .Net Core) have to either add platform-specific code (for each OS) or use an externally hosted URL.

As I've mentioned, not impossible, but extra work and a pitfall given that the functionality is called out in the SMART App Launch spec.

view this post on Zulip Gino Canessa (Nov 12 2020 at 20:12):

Yep, this is all about standalone apps - assuming those will be getting more and more common as regulations push for patient access.

view this post on Zulip Grahame Grieve (Nov 12 2020 at 20:21):

it's certainly a challenge. the solution I ended up with was to put a server up that handles the redirect for me, and allow applications to register their session id and port with the server. That's not super exciting but it saves from the hassle of needing admin access, which is pretty much yes or no, you'll never get it

view this post on Zulip Gino Canessa (Nov 12 2020 at 20:29):

I'd also note that this feels like a somewhat arbitrary hoop to jump through.

Knowing that protocol handling is an OS config (e.g., registry, info.plist, etc.), a malicious app is just as able to grab those URLs as not. It's only 'safer' if you require signed apps (e.g., UWP, iOS), but [desktop OSes] can't limit that functionality across the board. In some ways I'd argue that an app telling you "I have 127.0.0.1:62193 right now, redirect to that" is actually safer, as once the port is locked, nobody else can get it. (and most OSes don't allow capturing packets of loopback).

view this post on Zulip Gino Canessa (Nov 12 2020 at 20:34):

Grahame, yes. If you are running your own server already (that allows arbitrary code) that's likely the best option. For people wanting to write a their first client app, that's a high bar. I'm tinkering with an idea that will hopefully be able to run on the 'free-tier' of cloud providers without much effort, but it's a bit down the list.

view this post on Zulip Grahame Grieve (Nov 12 2020 at 20:40):

agree it's a high bar indeed. But... if people just want to hack, local.healthintersections.com.au always resolves to 127.0.0.1

view this post on Zulip Michele Mottini (Nov 12 2020 at 20:58):

Wouldn't most people write apps either as HTML/JavaScript or native for phones? I would think that writing native Windows or Mac native apps would be pretty unusual?

view this post on Zulip Gino Canessa (Nov 12 2020 at 20:58):

Grahame: nice!

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:02):

Michele: possibly? maybe? depends on the use case? I've received a lot of questions about it, and seen other streams with similar questions (not dynamic port specifically - how to use SMART via a native desktop app).

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:03):

@Gino Canessa your assertion that the localhost method is somehow more secure - do you have doc or more information on why that would be true?

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:04):

This isn't something we've been asked to support, and we do have native apps that are standalone that have integrated

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:04):

though right now it may be limited to android or ios

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:05):

(we do have windows, non-mobile apps that integrate using .Net today as well)

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:09):

@Jenni Syed , nothing specific to point to, just following the workflows:

Using protocol handler (Windows):

  • I write an app and register awesomeHealthApp://
  • Malicious app on my computer looks at the registry and inserts itself (e.g., takes over awesomeHealthApp:// and gives my app a phony launch via shell-execute).
  • I've been MITM attacked, and have no idea it happened.

Using dynamic loopback:

  • I write an app and grab a port (exclusive)
  • I ask for redirection to the port I currently own

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:15):

I'll also be the first to admit that the Windows platform for this is a bit of a mess (though I also can't fault the OS for this - backwards compatibility is hard). Even using MSAL to auth against AAD there are different paths for: UWP, .Net Desktop, and everything else.

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:19):

If the app had the ability to take over your registry entry... won't it also have the ability to kill the process that reserved the port?

view this post on Zulip Grahame Grieve (Nov 12 2020 at 21:20):

the user might notice that.

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:21):

@Grahame Grieve I am not a windows expert... what indication would there be to the user?

view this post on Zulip Grahame Grieve (Nov 12 2020 at 21:21):

the window they are working with disappears

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:22):

The registry entry is in HKCR, so it's not actually tied to any app-specific permission (IIRC). Killing my app means I restart and get a new port - yes it has the old one, but I am aware this happened and can take appropriate action (note: that app would also have have to kill my app after a login request is launched and before a redirect happened to have any impact at all)

edit: vs. modifying the registry, which can be done at any time and will not be apparent to the user/app (unless it goes and checks the registry at each launch - which may be a good practice to note)

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:24):

I'll also note that this isn't a hill I'd like to die on - if it's not supported, it's not supported. I started this thread because I assumed this was the preferred process (from the spec) and Josh thought it was unlikely to be supported. I feel that excluding it is odd, but :shrug:

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:29):

@Gino Canessa Technically, aren't native apps like this public? IE: any app that knows your client id can get a token on the app's behalf since the redirect just requires a localhost port? (I would also need to look at privs required to set this up to see if they would be commonly given to apps on an EHR desktop)

view this post on Zulip Jenni Syed (Nov 12 2020 at 21:29):

and yes, custom schemes also have their own issues :)

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:33):

@Jenni Syed Probably? Again, I'd argue no different than using a protocol handler (e.g., if I want to intercept something with a protocol handler on my desktop, it is just as trivial).

view this post on Zulip Gino Canessa (Nov 12 2020 at 21:36):

For me, it's a spectrum. Nothing running on my desktop machine is actually confidential - it's just a matter if I feel like investing enough time/effort to make that true. Entirely secure platforms are a different story.

edit: preemptive - yes, there are processes that can make software effectively confidential (e.g., hardware encryption, etc.), but I'm assuming that is well beyond the scope of what we're talking about here.


Last updated: Apr 12 2022 at 19:14 UTC