taler-docs

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

052-libeufin-bank-2fa.rst (7353B)


      1 DD 52: LibEufin Bank Two-factor authentification
      2 ################################################
      3 
      4 :Design status: Superseded
      5 :Implementation status: Implemented
      6 :DD shepherd: TBD
      7 :Historical contributors: Antoine A
      8 :First published: 2023-12-15
      9 :Last substantive change: 2023-12-15
     10 :Implementation evidence: taler-docs (2025-09-18), libeufin (2025-10-08)
     11 :Superseded by: Core Bank API v10 two-factor challenge protocol
     12 :Normative references: ``core/api-corebank.rst``
     13 
     14 .. warning::
     15 
     16    This unresolved alternatives document is historical and non-normative.  The
     17    implemented two-factor challenge protocol is specified by the current Core
     18    Bank API.
     19 
     20 Summary
     21 =======
     22 
     23 This document proposes designs for supporting 2-FA for more operations in
     24 libeufin-bank.
     25 
     26 Motivation
     27 ==========
     28 
     29 Currently, only cashout operations are protected using 2-FA and we want to also
     30 protects withdrawal, transactions, account reconfiguration and account deletion.
     31 
     32 Requirements
     33 ============
     34 
     35 * Support future TAN channels (YubiKey, trusted devices, etc) without API-breaking changes
     36 * Support multiple TAN channels per user
     37 
     38 Proposed Solutions
     39 ==================
     40 
     41 2 kinds of operations
     42 ^^^^^^^^^^^^^^^^^^^^^
     43 
     44 We have two kinds of operations we would like to protect:
     45 
     46 * state-machine operations that already have a ``pending`` and ``confirmed`` status and require multiple endpoint calls to complete (cashout and withdrawal).
     47 * one-shot operations that are currently completed using a single endpoint call (transaction, account reconfiguration and account deletion).
     48 
     49 Fine-grained or coarse-grained authentification
     50 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     51 
     52 * Fine-grained authorization is when one challenge is linked to a unique unalterable operation. They are the most secure and have the usability advantage that clients can show users exactly what they are allowing. They are complicated to implement especially for one-shot operations.
     53 * Coarse-grained authorization is when each challenge allows to perform one or many protected operations of any kind. They are the simplest to implement and might be enough for our needs.
     54 
     55 We should also take in consideration how hard it would be to maintain the solution and how hard it would be to protect a new kind of operation in the future.
     56 
     57 State machines operations only
     58 ------------------------------
     59 
     60 If we transform all operations to become state-machine ones, we can use the same design currently used for cashout operations. All operations are created in a ``pending`` state and need to be confirmed later. The TAN challenge code is sent when the operation is created and checked during confirmation. Operation creation is idempotent and can be used to trigger code retransmission.
     61 
     62 The good
     63 ^^^^^^^^
     64 
     65 + Fine-grained authorization
     66 
     67 The bad
     68 ^^^^^^^
     69 
     70 - Requires to store pending operations in the database, requires new tables to store pending state for one-shot ones
     71 - Requires to add many endpoints to track operations status, list pending operations, confirm operations, etc
     72 - Requires to mix TAN challenge logic with operation logic, this means asking for TAN channel alongside operation data and returning TAN specific error in all operation creation and confirmation endpoints, therefore TAN logic changes can impact all those endpoints
     73 - Operation logic rewrite
     74 - Big backend and database change (new table or column and new API per operation)
     75 
     76 
     77 Centralized 2FA endpoints
     78 -------------------------
     79 
     80 To improve upon the previous design we can separate endpoints to perform TAN challenges from operation ones. When creating operations they return a challenge ID that can be used with TAN-specific endpoints to receive and solve a challenge. Those endpoints will handle the TAN channel choice and TAN-specific errors. Protected endpoints will error when a pending challenge hasn't been solved.
     81 
     82 The good
     83 ^^^^^^^^
     84 
     85 + Fine-grained authorization
     86 + Centralized TAN challenge logic and error handling, TAN logic changes only impact TAN-specific endpoints
     87 
     88 The bad
     89 ^^^^^^^
     90 
     91 - Requires to store pending operations in the database
     92 - Requires adding many endpoints to track operations status, confirm operations, list pending operations, etc.
     93 - Operation logic rewrite
     94 - Big backend and database change (new table or column and new API per operation)
     95 
     96 2FA tokens
     97 ----------
     98 
     99 To improve upon the previous design, if coarse-grained authorization is enough, we can have a simpler design where a successful challenge produces a one-use 2FA token. Protected endpoints will error when a 2FA token is required and the token is provided through an HTTP header.
    100 
    101 We could require a 2FA token when confirming state-machine operations or when performing one-shot ones. Removing the need for new database tables and operation endpoints.
    102 
    103 The good
    104 ^^^^^^^^
    105 
    106 + Existing database tables stay the same
    107 + Centralized TAN challenge logic and error handling
    108 + Most endpoints stay the same except the cashout API
    109 + Can protect new operations without changing their logic but need to add token consumption logic to the database transaction
    110 + Small backend and database change per operation (token consumption logic)
    111 
    112 The bad
    113 ^^^^^^^
    114 
    115 - Using a nonstandard header can be complicated for some clients
    116 - The pending state of one-shot operations is kept at the client level, this is a simplification for the backend but we do not want to lose this state. This might be easy to do as all oneshot operations are simple ones and the token can be obtained in advance.
    117 - Coarse-grained authorization, one token for any operation. We could fix this by adding a ``kind`` field and an optional ``operation_id`` (state-machine operation) or ``operation_body`` (one-shot operations) field per challenge but this is ugly.
    118 
    119 2FA auth tokens
    120 ---------------
    121 To improve upon the previous design, we could reuse the existing authentification token logic and create a new scope, ``2fa``, that works as an augmented ``readwrite``. Those auth tokens would be valid for a short amount of time (~3 minute) and would not be refreshable.
    122 
    123 The good
    124 ^^^^^^^^
    125 
    126 + Existing database tables stay the same
    127 + Centralized TAN challenge logic and error handling
    128 + Most endpoints stay the same except the cashout API
    129 + Can protect new operations without changing their logic
    130 + Trivial backend and database change per operation (one line of code per operation)
    131 
    132 The bad
    133 ^^^^^^^
    134 
    135 - Having a short-term token in addition to a long-term refreshable token can be confusing for clients.
    136 - We still keep the pending state of one-shot operations at the client level.
    137 - Coarse-grained authorization, one token for any operation for a short amount of time.
    138 
    139 Q / A
    140 =====
    141 
    142 * Q: Where do we want to handle TAN challenges logic and error handling, in each operation API or a TAN-specific API?
    143 
    144   * In each operation means fewer API calls and TAN-specific means more API calls but better/cleaner logic separation.
    145 
    146 * Q: Where do we want to store pending states for oneshot transactions in the client or the backend database?
    147 
    148   * In the client makes things simpler for the backend but is incompatible with coarse-grained authorization.
    149 
    150 * Q: Do we need coarse-grained authorization or fine-grained is enough?
    151 
    152   * Coarse-grained authorization requires that we store pending states for operations even for the ones that are currently oneshot. We could use a different strategy for each kind.