taler-docs

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

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