From 3cba35cb301c527edd4e6d8ccc39be9a400c3147 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 8 Apr 2020 22:21:08 +0530 Subject: design document: new browser integration --- design-documents/001-new-browser-integration.rst | 179 +++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 design-documents/001-new-browser-integration.rst (limited to 'design-documents/001-new-browser-integration.rst') diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst new file mode 100644 index 00000000..1601f716 --- /dev/null +++ b/design-documents/001-new-browser-integration.rst @@ -0,0 +1,179 @@ +Design Doc 001: New Browser Integration +####################################### + +.. note:: + + This design document is currently a draft, it + does not reflect any implementation decisions yet. + +Summary +======= + +A new and improved mechanism for the integration of GNU Taler wallets with web +browsers is proposed. The mechanism is meant for browsers that support the +WebExtension API, but do not have native support for GNU Taler. + +The new approach allows the wallet extension to be installed without +excessive, "scary" permissions, while being simpler and still flexible. + + +Motivation +========== + +The current browser integration of the GNU Taler wallet relies heavily being +able to hook into various browser mechanisms via the following mechanisms: + +* A blocking ``webRequest`` handler that is run for every request the browser + makes, and looks at the status code and the presence of a "``Taler:``" HTTP header. +* A content script that's injected on every (!) page, which injects CSS (for + wallet presence detection) and JavaScript listeners into the page. The + injection is opt-in via a "data-taler" tag on the root html element. + +This has multiple problems: + +* It requires excessive permissions on **all** Websites. This is scary for us (in case we mess up) + and for users. It also slows down the publication of the extension on extension stores. +* We have not measured the performance implications, but our JavaScript code is executed for every + single request the browser is making. +* The CSS-based wallet detection integration is not very flexible. Only being able + to show/hide some element when the wallet is detected / not detected might not be + the optimal thing to do when we now have mobile wallets. + + +Requirements +============ + +* The new browser integration should require as few permissions as possible. + In particular, the wallet may not require "broad host" permissions. +* Fingerprinting via this API should be minimized. +* It must be possible for Websites to interact with the wallet without using JavaScript. +* Single Page Apps (using JavaScript) should be able to interact the wallet without + requiring a browser navigation. + + +Proposed Solution +================= + +We first have to accept the fundamental limitation that a WebExtension is not +able to read a page's HTTP request headers without intrusive permissions. +Instead, we need to rely on the content and/or URL of the fallback page that is +being rendered by the merchant backend. + +To be compatible with mobile wallets, merchants and banks **must** always render a fallback +page that includes the same ``taler://`` URI. + +Manual Triggering +----------------- + +Using the only the ``activeTab`` permission, we can access a page's content +*while and only while* the user is opening the popup (or a page action). +The extension should look at the DOM and search for ``taler://`` links. +If such a link as been found, the popup should display an appropriate +dialog to the user (e.g. "Pay with GNU Taler on the current page."). + +Using manual triggering is not the best user experience, but works on every Website +that displays a ``taler://`` link. + +.. note:: + + Using additional permissions, we could also offer: + + * A context ("right click") menu for ``taler://pay`` links + * A declarative pageAction, i.e. an additional clickable icon that shows up + on the right side of the address bar. Clicking it would lead to directly + processing the ``taler://`` link. + + It's not clear if this improves the user experience though. + + +Fragment-based Triggering +------------------------- + +This mechanism improves the user experience, but requires extra support from merchants +and broader permissions, namely the ``tabs`` permission. This permission +is shown as "can read your history", which sounds relatively intrusive. +We might decide to make this mechanism opt-in. + +The extension uses the ``tabs`` permission to listen to changes to the +URL displayed in the currently active tab. It then parses the fragment, +which can contain a ``taler://`` URI, such as: + +.. code:: none + + https://shop.taler.net/checkout#taler://pay/backend.shop.taler.net/-/-/2020.099-03C5F644XCNMR + +The fragment is processed the same way a "Taler: " header is processed. +For examle, a ``taler://pay/...`` fragment navigates to an in-wallet page +and shows a payment request to the user. + + +Fragment-based detection +------------------------ + +To support fragment-based detection of the wallet, a special +``taler://check-presence/${redir}`` URL can be used to cause a navigation to +``${redir}`` if the wallet is installed. The redirect URL can be absolute or +relative to the current page and can contain a fragment. + +For example: + +.. code:: none + + https://shop.taler.net/checkout#taler://check-presence/taler-installed + + -> (when wallet installed) + + https://shop.taler.net/taler-installed + + +To preserve correct browser history navigation, the wallet does not initiate the redirect if +the tab's URL changes from ``${redir}`` back to the page with the ``check-presence`` fragment. + + +Asynchronous API +---------------- + +The fragment-based triggering does not work well on single-page apps: It +interferes with the SPA's routing, as it requires a change to the navigation +location's fragment. + +The only way to communicate with a WebExtension is by knowing its extension ID. +However, we want to allow users to build their own version of the WebExtension, +and extensions are assigned different IDs in different browsers. We thus need +a mechanism to obtain the wallet extension ID in order to asynchronously communicate +with it. + +To allow the Website to obtain this extension ID, we can extend the redirection URL +of the ``taler://check-presence`` fragment to allow a placeholder for the extension ID. + +.. code:: none + + https://shop.taler.net/checkout#taler://check-presence/#taler-installed-${extid} + + -> (when wallet installed) + + https://shop.taler.net/checkout#taler-installed-12345ASDFG + +.. warning:: + + This allows fingerprinting, and thus should be an opt-in feature. + The wallet could also ask the user every time to allow a page to obtain the + +.. note:: + + To avoid navigating away from an SPA to find out the extension ID, the SPA + can open a new tab/window and communicate the updated extension ID back to + original SPA page. + + +Alternatives +============ + +* manual copy&paste of ``taler://`` URIs :-) +* integration of GNU Taler into all major browsers :-) +* convincing Google and/or Mozilla to provide better support + for reacting to a limited subset of request headers in + a declarative way +* convince Google and/or Mozilla to implement a general mechanism + where extensions can offer a "service" that websites can then + connect to without knowing some particular extension ID. -- cgit v1.2.3