taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

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