I have a use case where I need a factory-reset tablet device to install and run a simple Progressive Web Application (PWA). The tablet will be mounted on a wall inside a company building that may host unaccompanied external visitors from time to time. The PWA needs to initiate a websocket connection with a single JSON Web Token (JWT) to authenticate/authorize the connection. The PWA then just listens for new information coming through the websocket connection and displays it on the tablet. The intention is to show the currently-displayed information "publicly" to anybody walking by (including external visitors), without them having to do any kind of interaction at all with the tablet (indeed, no interaction will be supported in the PWA interface). I believe this is often termed a "kiosk display".
Although the information in the feed isn't anything particularly sensitive by design, we would like to prevent the case where a malicious person "inspects" the device (perhaps using a laptop, a cable and relevant software tools) and manages to obtain the JWT. The attacker's aim would be to duplicate the connection on another device, allowing them to record data from the feed for an indefinite period of time after they've left the building.
A key requirement of the the PWA is that it should continue to function (i.e. continue to show the feed information) even if the device is restarted (e.g. after an Android/iOS update), the PWA "refreshed" (sliding finger down), or the PWA closed and re-opened.
Our current thinking for securing the setup is along the lines of:
When the admin first installs the tablet, they go through a "pairing" process using a back-end system. They do this by opening a normal browser (e.g. Chrome) on the tablet and navigating to a certain HTTPS URL. The webpage will ask them for an identifier of the feed they want to connect to, as well as the current short-lived "pairing verification PIN" that the admin can only see when logged into the back-end dashboard (they'd be looking at this dashboard on another device).
When the admin submits the information (regular form POST), the server validates it and, assuming success, redirects the browser to another page that contains a unique and unpredictable link to the dynamically-generated PWA manifest for that unique pairing operation. Specifically, the
start_url
property in the PWA manifest includes an encrypted query string containing JWT for initiating the websocket connection.From that page, the admin then just installs the PWA to the device and closes the browser they were using.
The admin then starts the PWA, which makes the websocket connection (because it can get it from the query string of the
start_url
) and starts displaying the information. The PWA will continue to work after refresh/restarts because it will always just have the samestart_url
with the JWT in it.
Now even though the PWA will be in "standalone" mode and it won't be possible to easily see the "address bar", it seems to us that it's probably still possible for somebody to "inspect" the device and either manage to find the PWA manifest somehow, or manage to inspect the current URL of the running PWA, either of which would expose the JWT.
The second part of our idea, to help prevent the consequences of this, is to have the websocket server deny any attempt to make a second active connection with the same JWT. That is, when validating a connection request, the websocket server will check to see if there is already an existing connection open that was made with that JWT, and deny it if there is. The intuition here is that an attacker, even if they were able to get the JWT, would have to stop the PWA on the wall tablet in order to be able to establish a connection on their other device. After a short time, people in the building would soon realize there's something wrong with the tablet, and realize that they aren't able to start its PWA. They'd then go through a fresh pairing process (which involves the server killing all active connections, including the attacker's, thereby resolving the problem).
My question: Assuming that the core elements of a 1) "public tablet", 2) a PWA and 3) a websocket connection with JWT are non-negotiable, is there any other approach that might be more secure? Said otherwise, is there any mechanism that would allow us to store a JWT in such a way that the PWA could use it as required to make (and re-establish as required) websocket connections, but without it being "inspectable" by somebody who physically had control of the device?
If there's no better way, are there any practical security risks of the approach I've described that I may not have thought about?
Finally, am I right in stating that "native" mobile apps might have advantages over PWAs in this respect, because "native" apps are able to use more of the device's features and could potentially store "secrets" in a more advanced way than a PWA can?