taler-docs

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

post-token.rst (7212B)


      1 .. http:post:: /token
      2 
      3   This is the token endpoint of the OAuth 2.0 specification.
      4   This endpoint is used by the client to provide its authorization code,
      5   demonstrating that it has the right to learn a particular user's validated
      6   address.  In return, the challenger service returns the access token.
      7   Renewal is not supported.
      8 
      9   **Request:**
     10 
     11   The request must include an ``application/x-www-form-urlencoded`` body
     12   (``multipart/form-data`` is accepted as well)
     13   specifying the ``client_id``, ``redirect_uri``, ``client_secret``, ``code``
     14   and ``grant_type``.  The ``grant_type`` must be set to
     15   ``authorization_code``.  The ``redirect_uri`` must match the URI from
     16   ``/authorize``. The ``code`` must be the authorization code that ``/solve``
     17   returned to the user.  The ``client_id`` and ``client_secret`` must match
     18   the usual client credentials. Since protocol **v3**, ``code_verifier`` can also be included.
     19 
     20   The request body is limited to 2048 bytes, as is each individual field.
     21   Note that the client credentials must be passed in the body
     22   (``client_secret_post``); HTTP Basic authentication
     23   (``client_secret_basic``) is not supported.
     24 
     25   **Response:**
     26 
     27   Error responses follow RFC 6749, section 5.2 with an "error" field in JSON,
     28   as well as also returning GNU Taler style error messages.  The ``error``
     29   values used are ``invalid_request``, ``unsupported_grant_type``,
     30   ``invalid_client``, ``invalid_grant`` and ``server_error``.
     31   Since protocol **v8** every error response of this endpoint carries the
     32   ``error`` field, including ``415``, ``413`` and ``500``.
     33 
     34   :http:statuscode:`200 OK`:
     35     The body will be a `ChallengerAuthResponse`.
     36   :http:statuscode:`400 Bad Request`:
     37     A required POST field (``grant_type``, ``client_id``,
     38     ``client_secret``, ``code`` or ``redirect_uri``) is missing
     39     or malformed, ``grant_type`` is not ``authorization_code``,
     40     or the authorization code was not accepted.
     41     Error codes used are:
     42 
     43     * ``TALER_EC_GENERIC_PARAMETER_MISSING`` (``error`` is
     44       ``invalid_request``, or ``invalid_grant`` for a missing
     45       ``code_verifier``) --- a required field is absent; ``detail`` names it.
     46     * ``TALER_EC_GENERIC_PARAMETER_MALFORMED`` (``error`` is
     47       ``invalid_request``, or ``unsupported_grant_type`` when the
     48       ``grant_type`` is not ``authorization_code``) --- the
     49       ``Content-Length`` header is not a number,
     50       ``client_id`` is not a number, or the ``code_verifier`` violates the
     51       length (43--128) or character-set rules of RFC 7636.
     52     * ``TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE`` (``error`` is
     53       ``invalid_grant``) --- the ``code`` is not well-formed, does not
     54       correspond to a solved validation of this client, does not match its
     55       recomputed authentication tag, or the ``code_verifier`` does not
     56       match the stored ``code_challenge``.
     57     * ``TALER_EC_CHALLENGER_GRANT_UNKNOWN`` (``error`` is
     58       ``invalid_grant``) --- the authorization code was already redeemed,
     59       or the validation expired between the two database transactions.
     60 
     61     .. note::
     62 
     63       Several of these conditions are answered with a byte-identical
     64       response on purpose, so that a caller cannot use ``/token`` as an
     65       oracle to distinguish "this nonce does not exist" from "this
     66       validation has no address" from "your authentication tag is wrong".
     67   :http:statuscode:`401 Unauthorized`:
     68     Authentication of the *client* failed (per RFC 6749, section 5.2):
     69     either the ``client_id``/``client_secret`` pair is invalid, or the
     70     ``redirect_uri`` does not match the one registered with the client.
     71     Error codes used are:
     72 
     73     * ``TALER_EC_CHALLENGER_CLIENT_AUTHENTICATION_FAILED`` --- the
     74       ``client_id``/``client_secret`` pair does not match a registered
     75       client.  Since protocol **v8**; previously
     76       ``TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN``, which is now used
     77       only by :http:post:`/setup/$CLIENT_ID </setup/$CLIENT_ID>` with a
     78       ``404`` so that each error code maps to exactly one HTTP status.
     79     * ``TALER_EC_CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI``
     80 
     81     Both are returned with ``error`` set to ``invalid_client`` and a
     82     ``WWW-Authenticate: Bearer error="invalid_client"`` header.
     83     Note that failures concerning the ``code`` itself --- including
     84     PKCE ``code_verifier`` mismatches, which exist since protocol **v3**
     85     --- are reported with ``400``, not ``401``.
     86   :http:statuscode:`405 Method Not Allowed`:
     87     The request used a method other than ``POST`` or ``OPTIONS``.
     88     Returned by the request router with an ``Allow`` header and an
     89     **empty body**; in particular there is no Taler error code.
     90   :http:statuscode:`409 Conflict`:
     91     A ``code`` was presented for a validation process for which
     92     the user has not (yet) submitted any address, so the token
     93     cannot be issued.  Returned with
     94     ``TALER_EC_CHALLENGER_MISSING_ADDRESS``.
     95     Removed in **v8** (to better match RFC 6749, section 5.2);
     96     the condition is now reported as ``400`` with
     97     ``TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE``.
     98   :http:statuscode:`413 Request entity too large`:
     99     The request body exceeds the 2048 byte limit.
    100     Returned with ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT`` and ``error``
    101     set to ``invalid_request``.
    102   :http:statuscode:`415 Unsupported Media Type`:
    103     The ``Content-Type`` is missing or is not one the service can parse.
    104     Returned with ``TALER_EC_GENERIC_PARAMETER_MALFORMED``, ``detail`` set
    105     to ``"Content-Type"`` and ``error`` set to ``invalid_request``.
    106     Since protocol **v8**; previously reported as ``400``.
    107   :http:statuscode:`500 Internal Server Error`:
    108     The challenger service encountered an internal error,
    109     for example a database failure or a failure of the SHA-256
    110     or Base64 helpers used for PKCE verification.
    111     Error codes used are:
    112 
    113     * ``TALER_EC_GENERIC_DB_FETCH_FAILED`` --- ``detail`` is
    114       ``"get_client"`` or ``"get_validation_pkce"``.
    115     * ``TALER_EC_GENERIC_DB_STORE_FAILED`` --- ``detail`` is
    116       ``"do_insert_token"``.
    117     * ``TALER_EC_GENERIC_DB_SOFT_FAILURE`` --- a serialization failure that
    118       survived all retries.
    119     * ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE`` (``error`` is
    120       ``server_error``) --- the stored validation has a ``code_challenge``
    121       but no challenge method.
    122     * ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE`` (``error`` is
    123       ``server_error``) --- the SHA-256 or Base64 helper used for PKCE
    124       verification failed.
    125 
    126     All of these carry ``error`` set to ``server_error``.  Note that the
    127     stored ``code_challenge_method`` being unknown is reported with
    128     ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE`` since protocol **v8**;
    129     it previously used ``TALER_EC_GENERIC_PARAMETER_MALFORMED``, which
    130     wrongly suggested the client's request was at fault.
    131 
    132   **Details::**
    133 
    134   .. ts:def:: ChallengerAuthResponse
    135 
    136     interface ChallengerAuthResponse {
    137       // Token used to authenticate access in ``/info``.
    138       access_token: string;
    139 
    140       // Type of the access token.
    141       token_type: "Bearer";
    142 
    143       // Amount of time that an access token is valid (in seconds).
    144       expires_in: Integer;
    145 
    146     }