039-taler-browser-integration.rst (9820B)
1 DD 39: Taler Wallet Browser Integration Considerations 2 ###################################################### 3 4 Summary 5 ======= 6 7 This design document discusses considerations for integrating the GNU Taler 8 wallet with browsers and highlights difficulties with the implementation of a 9 GNU Taler wallet as a cross-browser WebExtension. 10 11 Motivation 12 ========== 13 14 GNU Taler is a payment system based on open standards with a free and open 15 source reference implementation. The GNU Taler wallet is the main component 16 used by end users to manage their electronic cash balance and payments. 17 18 Payments with GNU Taler are typically initiated via a QR code or link that 19 contains a ``taler://pay/{merchant}/{order_id}`` URI. Navigating to such a 20 link should result in a context switch to the wallet, where the payment can can 21 be approved/declined, and the user is subsequently redirected to the merchant's 22 website again. 23 24 Other ``taler://`` URIs (for withdrawals, refunds, etc.) are also commonly 25 used, but not explicitly discussed in this document, as very similar 26 considerations apply. 27 28 There are multiple reference implementations available for multiple 29 platforms (command line, Android, iOS, WebExtension). 30 31 While native applications can register themselves as a handler for the 32 ``taler`` URI scheme, the story is different for WebExtensions: There is 33 currently no reasonable, cross-platform mechanism that allows a WebExtension to 34 register itself as the handler for the ``taler`` URI scheme. 35 36 This is unfortunate, as a WebExtension could otherwise easily provide a Taler 37 wallet implementation without requiring the user to install a native App, 38 providing a better and safer user experience. 39 40 The problems with individual browsers are: 41 42 * Firefox allows specifying ``protocol_handlers`` in the extension manifest. 43 However, this list only allows schemes with the prefix ``ext+`` and 44 schemes that are included in an allowlist. The ``taler`` URI scheme 45 is not part of this list yet. 46 * Chromium / Google Chrome allows extensions to use the 47 ``registerProtocolHandler`` API. However, the same allowlist restrictions 48 apply. Furthermore, the registered protocol scheme is not listed as the 49 extension's required/optional permissions. Instead, a different permission 50 prompt is dynamically shown to the user. 51 * Safari currently neither supports ``registerProtocolHandler`` nor the 52 ``protocol_handlers`` mechanism. 53 * Opera does not seem to have any support for WebExtension protocol handlers 54 either. 55 56 Another issue is that Websites can't easily find out whether a browser 57 extension handling the ``taler://`` protocol is installed. 58 59 Requirements 60 ============ 61 62 * No vendor lock-in: The integration should not require merchant 63 Websites to rely on a particular list of extension IDs but instead 64 any WebExtension to potentially handle ``taler://`` URIs 65 or other mechanisms that Websites can use to interact with Taler 66 wallets. 67 * Security: The integration mechanism should require as few 68 permissions as possible. 69 * Ergonomic user experience: As few clicks and permission 70 prompts as possible should be shown to the user. 71 * Ergonomic developer experience: The code size and 72 effort to trigger a Taler payment on a merchant's Website 73 should be minimized. 74 * Forward compatibility: The integration mechanism 75 should work smoothly with future browsers that 76 have native, built-in support for Taler payments. 77 78 Proposed Solution 79 ================= 80 81 .. note:: 82 83 As of 2023-01-23, we've decided to go ahead with the approach 84 described in this section. 85 86 Overview 87 ^^^^^^^^ 88 89 The following integration approaches between Websites and the Taler Wallet webextension 90 are provided: 91 92 1. Directly triggering a ``taler://...`` URI on page load (via a meta tag). 93 2. Overriding ``<a href="taler://..." onclick=...>`` tags to trigger the wallet. 94 The onclick handler (which must call preventDefault) can implement behavior 95 that happens only when the webextension is not available. 96 3. Future (possibly post-1.0): A ``window.taler`` JavaScript API that is injected 97 into every page that requests it via a meta tag. This is useful for SPAs that 98 want to programmatically trigger the Taler wallet. 99 100 101 Usage 102 ^^^^^ 103 104 To directly trigger the handling of a ``taler://`` URI on page load, the following meta tag can be used: 105 106 .. code:: 107 108 <meta name="taler-uri" content="taler://..."> 109 110 111 To enable additional communication features between a website and the GNU Taler Wallet webextension, the page must 112 include the following meta tag: 113 114 .. code:: 115 116 <meta name="taler-support" content="$features"> 117 118 where ``$features`` is a comma-separated list of features. 119 120 The following features are supported: 121 122 * ``uri`` will hijack anchor elements (``<a href="taler://..." onclick=...>``) and replace their onclick handler 123 with a different handler that lets the webexension wallet handle the ``taler://`` URI. 124 125 * ``callback`` will call the ``window.talerCallback`` callback with ``present: boolean`` to 126 indicate the presence of the webext wallet (``present: true``). On deinstallation/deactivation 127 of the extension, the callback will be called with ``present: false`` on a best-effort basis. 128 Websites **MUST NOT** rely the ``present: false`` callback to be fired. 129 130 * (future): ``api`` will inject the ``window.taler`` API into the page. 131 It is recommended to use the ``callback`` feature to wait until 132 the ``window.taler`` object is available, as it is provided asynchronously 133 by the extension. 134 135 136 Caveats and Comments 137 ^^^^^^^^^^^^^^^^^^^^ 138 139 * Anchor tag hijacking does not work in all use-cases, for example when a navigation 140 to a ``taler://`` URI is initiated programmatically or by pasting 141 the URI in the browser's address bar. 142 143 * The ``window.taler`` API injection may break some websites 144 (https://github.com/brave/browser-laptop/issues/13711). 145 146 * All these approaches require excessive permissions, as unfortunately, 147 browsers currently do not provide a safe way for the communication between a 148 WebExtension and the page without excessive permissions. This especially 149 applies if the Website does not know the extension's ID. Hard-coding the 150 extension IDs would violate the "no vendor lock-in requirement". 151 152 * A neat feature of the anchor hijacking is that the ``taler://`` URI can be always be copied 153 in the browser (via "copy link address"). Clicking the link always results in either: 154 155 * The native URI handler, if no Taler Wallet webextension is installed and no onclick handler is defined 156 * The execution of the websites onclick handler if no Taler Wallet webextension is installed 157 * Triggering the webextension wallet to handle the ``taler://`` URI. 158 159 * Future ``window.taler`` injection should be based on user preferences on 160 sites where the user has explicitly accepted to disclose that they are a 161 Taler wallet user. 162 163 * There is no easy way to reliably and efficiently detect from within a content 164 script that a webextension has been installed. One possibility: 165 166 * The content script uses a ``onDisconnect`` handler for a port 167 to the background page / web worker. 168 * When this handler is invoked, either the extension was uninstalled 169 or the background page / web worker went to sleep. 170 We can figure out if the extension is still installed 171 by periodically checking ``chrome.runtime.id``. 172 * There is good way to invoke the ``window.talerCallback`` callback. One 173 possibility would be to communicate via another ``meta`` tag that the 174 content scripts creates when injected / the injected script observes. This 175 is very complex though. When the content script learns about the 176 uninstalled extension, the meta tag is removed. 177 178 * Note that other ways to communicate with the page are not available 179 anymore, as the extension has already been unloaded. 180 181 182 Other Alternatives 183 ================== 184 185 186 * Triggering interactions with the ``taler://`` URI in a ``Taler:`` HTTP 187 header. This approach would allow browsers with native Taler support 188 (or a WebExtension) to handle payment/withdrawal initiations directly, 189 without rendering a page that shows the QR code or link. 190 However, the WebExtension APIs do not allow extensions to 191 read particular headers without excessive permissions. Furthermore, 192 more recent versions of Chrome/Chromium do not allow blocking 193 processing of headers, leading to flickering when the extension 194 redirects based on the presence of the ``Taler:`` header. 195 196 * Browser and wallet presence detection. Merchants' Websites could include custom 197 code to detect the browser and/or presence of a Taler WebExtension and show 198 different instructions to guide the user towards processing the payment or to 199 show ``ext+taler`` URIs instead of ``taler`` URIs. This is not a viable 200 solution, as it requires a lot of extra and brittle logic on merchants' 201 Websites. 202 203 * Always use ``ext+taler`` URIs. This would help with Firefox. 204 Bad for forward compatibility, as we have already provisionally registered the 205 ``taler`` URI scheme. 206 207 * Web Payments API: Using the Web Payments API is not possible, because current 208 browsers do not allow specifying a WebExtension as a handler. Furthermore, 209 the Web Payments API would not support the withdrawal flow 210 (``taler://withdraw`` URIs). 211 212 * Browsers could provide anchor elements with a fallback when the protocol isn't supported, such as 213 ``<a href="taler://pay/..." handler-unavailable-href="https://wallet.taler.net/">...</a>``. 214 215 216 217 Related Work and References 218 =========================== 219 220 * **[1]** https://github.com/whatwg/html/issues/8596 221 * **[2]** https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers 222 * **[3]** https://github.com/ipfs/devgrants/blob/master/targeted-grants/protocol-handler-api-for-browser-extensions.md