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