taler-docs

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

049-auth.rst (8194B)


      1 DD 49: Authentication
      2 #####################
      3 
      4 Summary
      5 =======
      6 
      7 This design document specifies a simple authentication framework to be used by multiple Taler
      8 components that require authentication.
      9 
     10 Motivation
     11 ==========
     12 
     13 SPAs currently store the username and password in locals storage (or at least
     14 session storage).
     15 
     16 There's also no way to manage auth tokens third parties (e.g.
     17 auditors).
     18 
     19 Requirements
     20 ============
     21 
     22 * simple specification
     23 * simple implementation
     24 * simple to use
     25 * must cover two main use cases:
     26 
     27   * SPA login
     28   * delegating (possibly restricted) access to a third party using a token
     29 
     30 Proposed Solution
     31 =================
     32 
     33 We define a ``token`` endpoint that can be used to obtain access tokens from
     34 other forms of authentication, typically HTTP Basic auth.
     35 
     36 Token Creation
     37 --------------
     38 
     39 .. http:post:: /${RESOURCE...}/token
     40 
     41   Create an authentification token.
     42 
     43   **Request:**
     44 
     45   .. ts:def:: TokenRequest
     46 
     47     interface TokenRequest {
     48       // Service-defined scope for the token.
     49       // Typical scopes would be "readonly" or "readwrite".
     50       scope: string;
     51 
     52       // Server may impose its own upper bound
     53       // on the token validity duration
     54       duration?: RelativeTime;
     55 
     56       // Is the token refreshable into a new token during its
     57       // validity?
     58       // Refreshable tokens effectively provide indefinite
     59       // access if they are refreshed in time.
     60       // Deprecated, use ":refreshable" suffix in scope instead.
     61       refreshable?: boolean;
     62 
     63       // Optional token description
     64       // @since v4
     65       description?: string;
     66     }
     67 
     68   **Response:**
     69 
     70   :http:statuscode:`200 Ok`:
     71     The response is a `TokenSuccessResponse`
     72 
     73   **Details:**
     74 
     75   .. ts:def:: TokenSuccessResponse
     76 
     77     interface TokenSuccessResponse {
     78       // Expiration determined by the server.
     79       // Can be based on the token_duration
     80       // from the request, but ultimately the
     81       // server decides the expiration.
     82       expiration: Timestamp;
     83 
     84       // Opque access token.
     85       access_token: string;
     86     }
     87 
     88 Token Revocation
     89 ----------------
     90 
     91 Clients using session tokens log by forgetting the session token.
     92 Tokens can be explicitly revoked by making a ``DELETE`` request on
     93 the token endpoint.
     94 
     95 .. http:delete:: /${RESOURCE...}/token
     96 
     97   Invalidate the access token that is being used to make the request.
     98   **Authentication:**  The client must authenticate
     99   with a valid access token.
    100 
    101 Token Information
    102 -----------------
    103 
    104 List existing token informations.
    105 
    106 .. http:get:: /${RESOURCE...}/tokens
    107 
    108   **Request:**
    109 
    110   :query delta: *Optional.*
    111     Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned.  Defaults to ``-20`` to return the last 20 entries.
    112   :query start: *Optional.*
    113     Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
    114 
    115   **Response:**
    116 
    117   :http:statuscode:`200 OK`:
    118     Response is a `TokenInfos`.
    119   :http:statuscode:`204 No content`:
    120     No tokens.
    121 
    122   **Details:**
    123 
    124   .. ts:def:: TokenInfos
    125 
    126     interface TokenInfos {
    127       tokens: TokenInfo[];
    128     }
    129 
    130   .. ts:def:: TokenInfo
    131 
    132     interface TokenInfo {
    133       // Time when the token was created.
    134       creation_time: Timestamp;
    135 
    136       // Expiration determined by the server.
    137       // Can be based on the token_duration
    138       // from the request, but ultimately the
    139       // server decides the expiration.
    140       expiration: Timestamp;
    141 
    142       // Service-defined scope for the token.
    143       // Typical scopes would be "readonly" or "readwrite".
    144       scope: string;
    145 
    146       // Is the token refreshable into a new token during its
    147       // validity?
    148       // Refreshable tokens effectively provide indefinite
    149       // access if they are refreshed in time.
    150       refreshable: boolean;
    151 
    152       // Optional token description
    153       description?: string;
    154 
    155       // Time when the token was last used.
    156       last_access: Timestamp;
    157 
    158       // Opaque unique ID used for pagination.
    159       row_id: Integer;
    160     }
    161 
    162 Permissions
    163 ===========
    164 
    165 Each API request to an endpoint **may** be associated with a *permission*.
    166 A permission is a descriptive string, e.g. ``orders-read`` for a ``GET`` request on the endpoint ``/private/orders``.
    167 Another example would be ``orders-write`` for a ``POST`` or ``PUT`` request on the same endpoint.
    168 If no permission is defined for a request, no access control is enforced.
    169 
    170 Each component API **must** define and document appropriate permissions for its requests.
    171 Permission strings best practice include that *read-only* access end with the suffix ``-read``, e.g. ``orders-read``.
    172 If the access to the endpoint modifies the state it is suffixed with ``-write``, e.g. ``orders-write``.
    173 Special permissions may deviate from this.
    174 Two endpoints **may** use the same permission.
    175 
    176 In the API documentaction where the **Request** to an endpoint is defined, **Required permission** entry should be added.
    177 See the Merchant API for examples.
    178 
    179 Scopes
    180 ======
    181 
    182 A ``scope`` is a set of permissions that is associated with a token.
    183 The scope is provided when requesting the token, see `TokenRequest`.
    184 
    185 Default scopes that can be requested in a `TokenRequest` are or rather **must** be defined and documented by the component.
    186 Here are some *examples* of possible scopes:
    187 
    188 * ``readonly``: ``*-read`` -- This wildcard match will grant access to all endpoints protected with a permission that has the ``-read`` suffix.
    189 * ``admin``: ``*`` -- This matches all permissions, essentially the *key to the kingdom*.
    190 * ``orders-simple``: ``orders-read,orders-write`` -- Access to reading and writing orders.
    191 * ``orders-full``: ``orders-read,orders-write,orders-refund`` -- Like ``orders-simple``, but also allows for refunds.
    192 
    193 In the merchant component, scopes are currently hard-coded. In the future, additional scopes may be configurable
    194 through configuration files and/or default scopes overridden.
    195 
    196 Token refresh
    197 =============
    198 
    199 Tokens may be requested to be refreshable.
    200 In older API versions this was achieved by setting the ``refreshable`` field in the `TokenRequest`.
    201 In recent API versions this is achieved by suffixing the requested scope with ``:refreshable``, e.g. ``orders-full:refreshable``.
    202 
    203 Definition of Done
    204 ==================
    205 
    206 * DONE: spec reviewed
    207 * DONE: implemented in merchant backend
    208 * implemented in libeufin-bank
    209 * DONE: implemented in the bank webui SPA
    210 * implemented in the merchant backoffice SPA
    211 
    212 
    213 Alternatives
    214 ============
    215 
    216 * use something much closer to OAuth2
    217 
    218   * would be unnecessarly generic and complex
    219 
    220 Session Tokens / Signatures
    221 ---------------------------
    222 
    223 For performance reasons, OAuth 2.0 uses two types of tokens: Short-lived access
    224 tokens and long-lived refresh tokens.  The access tokens can be implemented via
    225 signatures and the long-lived refresh tokens via server-stored tokens.  This
    226 allows to cheaply validate access tokens, while still allowing longer expiration times
    227 for refresh tokens.
    228 
    229 We could do something similar by introducing login and session tokens.  A login
    230 token is a server-stored token.  In addition to being used directly as an
    231 access token, a login token can also be converted to a short-lived session
    232 token.
    233 
    234 Session access tokens should be implemented as "self-encoded tokens", i.e.
    235 as tokens signed by the server without requiring server-side token storage.
    236 Session access tokens should have a rather short maximum expiration.
    237 
    238 The signature should be over ``(username, kind, scope, creation_timestamp, expiry)``.
    239 
    240 To revoke session tokens, the server must store the timestamp of the last
    241 revocation and only accept tokens with a ``creation_timestamp`` larger than the
    242 last revocation timestamp. Individual session tokens cannot be revoked, only
    243 all issued session tokens can be revoked at once.
    244 
    245 However, we decided against doing this because the performance benefits
    246 are not significant enough for us and having multiple token types would
    247 lead to unnecessary complexity.
    248 
    249 Drawbacks
    250 =========
    251 
    252 * still more complex than simple auth tokens or HTTP basic auth
    253 
    254 Discussion / Q&A
    255 ================
    256 
    257 (This should be filled in with results from discussions on mailing lists / personal communication.)