単一Web Originでユーザ投稿アプリを安全に提供できるのか問題
最近libdatachannel https://github.com/paullouisageneau/libdatachannel がMPL2に再ライセンスされたのに気付いたので、ローカルのストレージとかネットワークはWebRTC経由の専用のネイティブアプリに提供させる方式で相当自由なWebアプリ環境が作れるんではないかという気がしている。
(昔は専用のネイティブプラグインをWebブラウザにインストールさせる -- UnityのWeb Playerとか -- という文化が存在したが、現状ではそういうのは難しいだろう)
が、当然 WebRTC をしゃべったりするためにはHTTPSでサイトを提供する必要があるので、そのHTTPSサイトのアーキテクチャを考える必要がある。
前提
https://unityroom.com/ のWebAssembly版を作りたい。
- 可能な限り安く実現する
- ユーザーにはブラウザ上のJavaScriptを直接は使わせない。WebAssemblyバイナリをアップロードさせるとか、ソースコードをGitHubからDLしてきてその場でコンパイルする。
- アプリはpersistentなストレージを持てる。
- アプリは外部と通信できる(http fetch、bluetooth、WebRTC上の独自プロトコルを経由したTCP/IPまたはEthernet)
- ユーザーのプライバシーを尊重する。つまり、アプリが生成したデータは他のアプリからは使用できない。
例えばbluetoothデバイスのペアリングはブラウザ上ではOrigin単位になるため、ユーザがペアリングしたデバイスをそのまま使わせるのはプライバシ的に問題がある。このため、ランタイムライブラリが追加のペアリング機構(デバイスとアプリのペアリングを行うもの)を用意しなければならない。
Glitch
Glitchはユーザーが任意の"サーバー側"JavaScriptを実行できるプラットフォームで、ユーザーアプリには1つのLinuxコンテナが提供され、Glitchはそのコンテナ内部のGitリポジトリと連携したエディタと、https reverse proxyを提供している。
Glitchは全てのアプリにユニークなWeb origin <アプリ名>.glitch.com
を付与している。そのためアプリ間の干渉問題は無い。
ただし、 <アプリ名>
の部分は他人に再利用される可能性があるため、センシティブなデータを作った場合(他所のサイトとログイン連携した等)はアプリを消すべきではない。
Codepen
Codepenはユーザーが任意の"クライアント側"JavaScriptを実行できるプラットフォームで、ユーザアプリには専用のWeb originを 払い出さない 方式になっている。
このため例えばLocalStorageを扱うPen(ユーザーアプリのこと)でセットしたLocalStorageは、他のPenから参照できる。
... じゃぁCodepen自体のセッションにPenからアクセスできてセキュリティ的にヤバいじゃんと思うが、その辺は流石に対策されていて、Penには共通のWeb origin cdpn.io
が与えられ、Codepen自体のアカウント管理には codepen.io
のWeb originが使われる。
Unityroom
UnityのWebGLビルドをアップロードできるサービス。Conoha.ioなiframe内で実行される。
Unityroom側にもTwitter連携があるが、ゲーム内からTweetするアセットは単にブラウザ側のpopupを呼んでいるだけで、特にUnityroom側と交信しているわけではないようだ。
積極的なセキュリティを提供しているサイトは無い
基本的にはユーザーアプリケーションをiframeなり独自ドメインなりで分離し、ユーザーアプリケーション同士は仲良くやってくれ方式が殆どのようだ。
まぁ真剣なアプリを作ること自体が原理的にできないので、そういう仕様でも実用上の問題が無いのだろう。
fetch
の抽象化が課題
現状想定している機能セットだと、fetchの抽象化が問題だろう。ユーザーによるJavaScriptを直接走らせることは無いので抽象化自体は簡単にできるが、ユーザーアプリケーションが通信したサーバに HttpOnly
なCookieをセットされるとランタイム側では気付けないという問題がある。
お金が無限にあるなら、いわゆるCORS proxy(e.g. https://github.com/Rob--W/cors-anywhere )と同様に、アプリからのhttp要求を一旦中継してしまうのが簡単に思える。ただ、これはアプリが発生させたトラフィック代をこちらが支払わなくてはならなくなるので避けたい。
... 良い方法が無さそうだから一旦無しにした方が良いかな。。?
ユーザー/アプリ毎にoriginを払い出す方式
fetch
にはユーザージェスチャは必要ないので、原理的には専用の隠しiframeに処理を代行させられる。このため、例えばユーザーやアプリのIDを埋め込んだ専用のoriginを払い出す方式が考えられる。
実際、Glitchは1アプリ1originにしているが、これだとアプリ間でoriginを共有できない(= アプリをアップデートしたときに過去のoriginが失われる可能性がある)。また、Glitchのアプリは明示的に作成する必要があるが、それだと手軽に(他人の)アプリを実行できないという問題もある。
ユーザー毎に払い出せはこれらの問題は解消するが、今度はプライバシーの問題がある(1 origin = 1 userなので特定ユーザーをサイトを越えてトラッキングできてしまう)。