We did it. We developed an enterprise app as a web app, but some of our customers insisted on having it run locally because of security concerns. So we just packaged up the server with a thin client and voila! What might have been a months-long re-development took a couple of hours.
MITM is not a problem, since the only communication with the socket is to read files etc from your local machine, and a malicious third party have nothing to gain, and no real way to fool you.
I've had this need a couple times. My scenario: web-based application that needs to use some usb-gadget (NFC reader for example).
You cannot access the device directly because there's no (standard) Browser <> NFC Reader API implemented in the browsers. You need native code to access that device. Yet your entire application is web-based, and it would be fine if only you could interface with that pesky gadget.
In the past, people used NPAPI plugins for that, but those days are gone (browser plugins are much more sandboxed now, so they just don't have those capabilities anymore).
Solution? You ship a companion small native app. That native app is supposed to interface your web application with the usb device. How do you achieve that? Simple, the native app exposes an http/websocket-based API at "localhost:someport" on the one side, and talks to the device using native drivers on the other.
If you don't use https in your web-app, that is it. Your web-app can now communicate with your native app (by making requests to "localhost:someport"), and through your native app communicate with the device. Problem solved... right?
Wrong, because your web application should be using https. For security reasons, the browser will _not_ allow connections from an https-page to a non-https (or secured web sockets) server. Thus, your native app's exposed API must use https/wss too. And here is where the article's ordeal begins.
> And could you not solve it with certificate pinning?
Pinning a certificate is not secure because using the same certificate in all installations is not secure: notice that your native app must have the certificate and the corresponding private key (because it must serve requests under that "localhost:port"). At this point, any of your users could just grab that cert/key pair (from their local installation) and use it to man-in-the-middle your other clients (the cert is valid for them too!).
The problem is exactly the same if you obtain a publicly-recognized certificate and distributed it with your native app.
The secure solution is, as the article says, to generate a certificate _specific for this user_ during the installation of your native app, and adding that certificate to the user's certificate store. This way the certificate is only valid for that user. Your native app can use this user-specific certificate to serve https/wss requests, and the user's browser will connect to that without warnings because the certificate is trusted. However, if user A extracts the certificate and key from her installation and tries to use them to main-in-the-middle another user B, it won't work because the certificate B trusts is his own installation-time-generated-one, not A's certificate which is different.
The article also says that the website could make requests to http://127.0.0.1:portnumber/ and browsers will allow that even from HTTPS websites.
Also, I'm willing to bet browsers will block that at some point too...