taler-docs

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

001-new-browser-integration.rst (8942B)


      1 XX 01: New Browser Integration
      2 ##############################
      3 
      4 :Design status: Superseded
      5 :Implementation status: Partial
      6 :DD shepherd: TBD
      7 :Historical contributors: Florian Dold
      8 :First published: 2020-04-08
      9 :Last substantive change: 2023-09-15
     10 :Superseded by: :doc:`039-taler-browser-integration`
     11 
     12 .. warning::
     13 
     14   We have decided not to follow through with the proposed solution in this
     15   design doc.  We care a lot about a nice upgrade path for when better
     16   browser integration becomes available.  Encouraging the ``#taler://`` fragment
     17   based integration might lead merchant frontends to **only** support this type
     18   of integration.
     19 
     20   Instead, the following path will be taken:
     21 
     22   1. CSS-based presence detection will be removed from the wallet,
     23      as there is no satisfactory upgrade path to better mechanisms
     24   2. Manual triggering will be implemented as described in this design doc.
     25   3. The ``webRequest`` permission that allows ``"Taler: "`` header based
     26      browser integration will become opt-in.
     27   4. The interactive API will be put on hold.  Instead, SPAs should
     28      ask the user to open the wallet popup (and/or render a QR code for mobile wallets).
     29   5. To enable easier integration for merchants, the reference merchant backend
     30      might include a page to trigger payments, which displays the QR code
     31      correctly, does long-polling via JS and serves the ``"Taler: "`` header.
     32   6. The presence detection ``taler://`` URI described in this document
     33      will **not** be supported, as allowing presence detection might
     34      encourage merchants to treat mobile / detached wallets as 2nd class
     35      citizens.
     36 
     37   The body below is retained for historical context and is non-normative.
     38 
     39 Summary
     40 =======
     41 
     42 A new and improved mechanism for the integration of GNU Taler wallets with web
     43 browsers is proposed.  The mechanism is meant for browsers that support the
     44 WebExtension API, but do not have native support for GNU Taler.
     45 
     46 The new approach allows the wallet extension to be installed without
     47 excessive, "scary" permissions, while being simpler and still flexible.
     48 
     49 
     50 Motivation
     51 ==========
     52 
     53 The current browser integration of the GNU Taler wallet relies heavily being
     54 able to hook into various browser mechanisms via the following mechanisms:
     55 
     56 * A blocking ``webRequest`` handler that is run for every request the browser
     57   makes, and looks at the status code and the presence of a "``Taler:``" HTTP header.
     58 * A content script that's injected on every (!) page, which injects CSS (for
     59   wallet presence detection) and JavaScript listeners into the page.  The
     60   injection is opt-in via a "data-taler" tag on the root html element.
     61 
     62 This has multiple problems:
     63 
     64 * It requires excessive permissions on **all** Websites.  This is scary for us (in case we mess up)
     65   and for users.  It also slows down the publication of the extension on extension stores.
     66 * We have not measured the performance implications, but our JavaScript code is executed for every
     67   single request the browser is making.
     68 * The CSS-based wallet detection integration is not very flexible.  Only being able
     69   to show/hide some element when the wallet is detected / not detected might not be
     70   the optimal thing to do when we now have mobile wallets.
     71 
     72 
     73 Requirements
     74 ============
     75 
     76 * The new browser integration should require as few permissions as possible.
     77   In particular, the wallet may not require "broad host" permissions.
     78 * Fingerprinting via this API should be minimized.
     79 * It must be possible for Websites to interact with the wallet without using JavaScript.
     80 * Single Page Apps (using JavaScript) should be able to interact with the wallet without
     81   requiring a browser navigation.
     82 
     83 
     84 Proposed Solution
     85 =================
     86 
     87 We first have to accept the fundamental limitation that a WebExtension is not
     88 able to read a page's HTTP request headers without intrusive permissions.
     89 Instead, we need to rely on the content and/or URL of the fallback page that is
     90 being rendered by the merchant backend.
     91 
     92 To be compatible with mobile wallets, merchants and banks **must** always render a fallback
     93 page that includes the same ``taler://`` URI.
     94 
     95 Manual Triggering
     96 -----------------
     97 
     98 Using only the ``activeTab`` permission, we can access a page's content
     99 *while and only while* the user is opening the popup (or a page action).
    100 The extension should look at the DOM and search for ``taler://`` links.
    101 If such a link has been found, the popup should display an appropriate
    102 dialog to the user (e.g. "Pay with GNU Taler on the current page.").
    103 
    104 Using manual triggering is not the best user experience, but works on every Website
    105 that displays a ``taler://`` link.
    106 
    107 .. note::
    108 
    109   Using additional permissions, we could also offer:
    110 
    111   * A context ("right click") menu for ``taler://pay`` links
    112   * A declarative pageAction, i.e. an additional clickable icon that shows up
    113     on the right side of the address bar.  Clicking it would lead to directly
    114     processing the ``taler://`` link.
    115 
    116   It's not clear if this improves the user experience though.
    117 
    118 
    119 Fragment-based Triggering
    120 -------------------------
    121 
    122 This mechanism improves the user experience, but requires extra support from merchants
    123 and broader permissions, namely the ``tabs`` permission.  This permission
    124 is shown as "can read your history", which sounds relatively intrusive.
    125 We might decide to make this mechanism opt-in.
    126 
    127 The extension uses the ``tabs`` permission to listen to changes to the
    128 URL displayed in the currently active tab.  It then parses the fragment,
    129 which can contain a ``taler://`` URI, such as:
    130 
    131 .. code:: none
    132 
    133   https://shop.taler.net/checkout#taler://pay/backend.shop.taler.net/-/-/2020.099-03C5F644XCNMR
    134 
    135 The fragment is processed the same way a "Taler: " header is processed.
    136 For example, a ``taler://pay/...`` fragment navigates to an in-wallet page
    137 and shows a payment request to the user.
    138 
    139 
    140 Fragment-based detection
    141 ------------------------
    142 
    143 To support fragment-based detection of the wallet, a special
    144 ``taler://check-presence/${redir}`` URL can be used to cause a navigation to
    145 ``${redir}`` if the wallet is installed.  The redirect URL can be absolute or
    146 relative to the current page and can contain a fragment.
    147 
    148 For example:
    149 
    150 .. code:: none
    151 
    152   https://shop.taler.net/checkout#taler://check-presence/taler-installed
    153 
    154   -> (when wallet installed)
    155 
    156   https://shop.taler.net/taler-installed
    157 
    158 
    159 To preserve correct browser history navigation, the wallet does not initiate the redirect if
    160 the tab's URL changes from ``${redir}`` back to the page with the ``check-presence`` fragment.
    161 
    162 
    163 Asynchronous API
    164 ----------------
    165 
    166 The fragment-based triggering does not work well on single-page apps: It
    167 interferes with the SPA's routing, as it requires a change to the navigation
    168 location's fragment.
    169 
    170 The only way to communicate with a WebExtension is by knowing its extension ID.
    171 However, we want to allow users to build their own version of the WebExtension,
    172 and extensions are assigned different IDs in different browsers.  We thus need
    173 a mechanism to obtain the wallet extension ID in order to asynchronously communicate
    174 with it.
    175 
    176 To allow the Website to obtain this extension ID, we can extend the redirection URL
    177 of the ``taler://check-presence`` fragment to allow a placeholder for the extension ID.
    178 
    179 .. code:: none
    180 
    181   https://shop.taler.net/checkout#taler://check-presence/#taler-installed-${extid}
    182 
    183   -> (when wallet installed)
    184 
    185   https://shop.taler.net/checkout#taler-installed-12345ASDFG
    186 
    187 .. warning::
    188 
    189   This allows fingerprinting, and thus should be an opt-in feature.
    190   The wallet could also ask the user every time to allow a page to obtain the
    191 
    192 .. note::
    193 
    194   To avoid navigating away from an SPA to find out the extension ID, the SPA
    195   can open a new tab/window and communicate the updated extension ID back to
    196   original SPA page.
    197 
    198 Once the Website has obtained the extension ID, it can use the ``runtime.connect()`` function
    199 to establish a communication channel to the extension.
    200 
    201 
    202 Alternatives
    203 ============
    204 
    205 * Manual copy&paste of ``taler://`` URIs :-)
    206 * Integration of GNU Taler into all major browsers :-)
    207 * Convincing Google and/or Mozilla to provide better support
    208   for reacting to a limited subset of request headers in
    209   a declarative way
    210 * Convince Google and/or Mozilla to implement a general mechanism
    211   where extensions can offer a "service" that websites can then
    212   connect to without knowing some particular extension ID.
    213 * Convince Google and/or Mozilla to add better support for
    214   registering URI schemes from a WebExtension, so that
    215   we can register a handler for ``taler://``.  For a better user experience,
    216   there should also be some way to check whether some particular URI scheme
    217   has a handler.
    218 
    219 Drawbacks
    220 =========
    221 
    222 * Firefox currently does not support messages from a website to an extension, and currently
    223   cannot support the asynchronous wallet API.
    224   There is a bug open for this issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1319168