taler-docs

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

api-challenger.rst (23852B)


      1 ..
      2   This file is part of GNU TALER.
      3   Copyright (C) 2023, 2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 2.1, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 
     16   @author Christian Grothoff
     17 
     18 .. _challenger-api:
     19 
     20 ==============================
     21 Challenger Service RESTful API
     22 ==============================
     23 
     24 The challenger service validates that a user is able to receive challenges at
     25 an address (such as e-mail or SMS) and allows an OAuth 2.0 client to obtain
     26 access to these validated addresses.
     27 
     28 The high-level flow is that an OAuth 2.0 client is first registered with the
     29 challenger service (via command-line). Using the command-line tool will print
     30 the resulting client ID to the console.
     31 
     32 .. note::
     33 
     34   Right now, registration of a unique redirection URI is *mandatory* for
     35   each client. If multiple redirection URIs are needed, it is suggested to
     36   just register additional clients.  (While OAuth 2.0 would support not
     37   registering fixed redirection URIs with a client, this is not recommended
     38   as it would create an open redirector.)
     39 
     40 Once a client is registered, that client can use the challenger service when
     41 it needs a user to prove that the user is able to receive messages at a
     42 particular address.  However, asking a user to prove access to a particular
     43 address can be expensive as it may involve sending an SMS or even postal mail
     44 depending on the type of address.  Thus, challenger does not allow a user
     45 agent to begin an address validation process without prior approval by a
     46 registered client.  Thus, the process begins with a ``/setup/$CLIENT_ID`` request where a
     47 client requests challenger to begin an address validation request.  The
     48 ``/setup/$CLIENT_ID`` response contains a ``nonce`` which is then used to construct the
     49 URL of the endpoint to which the client must redirect the user-agent to begin
     50 the address validation and authorization process.
     51 
     52 The client then redirects the user-agent to the ``/authorize/$NONCE`` endpoint
     53 of the challenger service, adding its ``state``, ``client_id`` and
     54 ``redirect_uri`` as query parameters.  The ``redirect_uri`` must match the
     55 redirect URI registered with the client. From this endpoint, the challenger
     56 service will return a Web page asking the user to provide its address.
     57 
     58 .. note::
     59 
     60   Challenger is a bit unusual in that the ``$NONCE`` in the endpoint URL
     61   makes the authorization endpoint URL (deliberately) unpredictable, while
     62   for many other OAuth 2.0 APIs this endpoint is static. However, this is
     63   compliant with OAuth 2.0 as determining the authorization URL is left out
     64   of the scope of the standard.
     65 
     66 When the user has filled in the form with their address, it will be submitted
     67 to the ``/challenge/$NONCE`` endpoint and the challenger service will send a
     68 challenge to the user's address and generate an HTML form asking the user to
     69 enter the received challenge value.
     70 
     71 The user can then enter the answer to the challenge which is then submitted to
     72 the ``/solve/$NONCE`` endpoint.  If the answer is correct, the user agent will
     73 be redirected to the client redirect URI that was specified by the OAuth 2.0
     74 client upon ``/authorize``, together with an authorization grant encoded in
     75 the redirection URI.
     76 
     77 Given this authorization grant, the OAuth 2.0 client can then use the
     78 ``/token`` endpoint to obtain an access token which will grant it access to
     79 the resource.
     80 
     81 Using the ``/info`` endpoint the client can then finally obtain the (now)
     82 verified address of the user.
     83 
     84 .. contents:: Table of Contents
     85   :local:
     86 
     87 
     88 ---------------
     89 Version History
     90 ---------------
     91 
     92 The current protocol version is **v6**.
     93 
     94 * The Challenger SPA is currently targeting **v6**.
     95 
     96 **Version history:**
     97 
     98 * ``v6``: add the ``address_type`` field to ``/config``
     99 
    100 **Upcoming versions:**
    101 
    102 * None anticipated.
    103 
    104 **Ideas for future version:**
    105 
    106 * ``vXXX``: marker for features not yet targeted for release
    107 
    108 
    109 .. include:: tos.rst
    110 
    111 .. _challenger-config:
    112 
    113 -----------------------
    114 Receiving Configuration
    115 -----------------------
    116 
    117 .. http:get:: /config
    118 
    119   Obtain the key configuration settings of the storage service.
    120 
    121   **Response:**
    122 
    123   :http:statuscode:`200 OK`:
    124     Response is a `ChallengerConfigurationResponse`.
    125 
    126   .. ts:def:: ChallengerConfigurationResponse
    127 
    128     interface ChallengerConfigurationResponse {
    129       // Name of the service
    130       name: "challenger";
    131 
    132       // libtool-style representation of the Challenger protocol version, see
    133       // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
    134       // The format is "current:revision:age".
    135       version: string;
    136 
    137       // URN of the implementation (needed to interpret 'revision' in version).
    138       // @since v0, may become mandatory in the future.
    139      implementation?: string;
    140 
    141       // @since **v2**.
    142       // Object; map of keys (names of the fields of the address
    143       // to be entered by the user) to objects with a "regex" (string)
    144       // containing an extended Posix regular expression for allowed
    145       // address field values, and a "hint"/"hint_i18n" giving a
    146       // human-readable explanation to display if the value entered
    147       // by the user does not match the regex. Keys that are not mapped
    148       // to such an object have no restriction on the value provided by
    149       // the user.  See "ADDRESS_RESTRICTIONS" in the challenger configuration.
    150       restrictions: Object;
    151 
    152       // @since **v6**
    153       // Defines the set of fields asked to the user.
    154       // The field names are registered via GANA at
    155       // https://git.taler.net/gana.git/tree/gnu-taler-form-attributes
    156       // email: CONTACT_EMAIL
    157       // phone: CONTACT_PHONE
    158       // postal: CONTACT_NAME, ADDRESS_LINES, ADDRESS_COUNTRY
    159       // postal-ch: CONTACT_NAME, ADDRESS_LINES
    160       address_type: "email" | "phone" | "postal" | "postal-ch";
    161 
    162       // Hint to show in the address bar for the user as an example for
    163       // the format of the address.
    164       address_hint: string;
    165     }
    166 
    167 .. _challenger-setup:
    168 
    169 -----
    170 Setup
    171 -----
    172 
    173 .. http:post:: /setup/$CLIENT_ID
    174 
    175   This endpoint is used by the client to authorize the execution of an address
    176   validation on its behalf.  An ``Authorization`` header (for now always using
    177   a ``Bearer`` token) should be included to provide the client's credentials
    178   to authorize access to the challenger service.  This token must match the
    179   ``client_secret`` from the registration of the client with the challenger
    180   service (which will also be used in the later ``/token`` request).
    181 
    182   **Request:**
    183 
    184   The body can be an address in JSON encoding to pre-initialize the address to
    185   be used by challenger for this process. If the body is absent, the user will
    186   have to enter the full address details.  The specific address format depends
    187   on the address type.  However, `ChallengeSetupRequest` defines the shared
    188   ``read_only`` bit that has a special meaning independent of the address type:
    189   it informs Challenger that the address should not be editable.
    190 
    191   Passing an address in the ``/setup`` body is supported @since protocol **v4**.
    192 
    193   **Response:**
    194 
    195   :http:statuscode:`200 OK`:
    196     Response is a `ChallengeSetupResponse`.
    197   :http:statuscode:`400 Bad request`:
    198     The request is malformed. Usually returned with an
    199     error code of ``TALER_EC_GENERIC_PARAMETER_MISSING`` or
    200     ``TALER_EC_GENERIC_PARAMETER_MALFORMED``.
    201   :http:statuscode:`404 Not found`:
    202     The challenger service is unaware of a matching client.
    203     or the credentials of the client are invalid.
    204     Usually returned with
    205     ``TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN``.
    206   :http:statuscode:`500 Internal server error`:
    207     The challenger service encountered an internal error.
    208     Usually returned with
    209     ``TALER_EC_GENERIC_DB_FETCH_FAILED`` or
    210     ``TALER_EC_GENERIC_DB_STORE_FAILED`` or
    211     ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE``.
    212 
    213   **Details::**
    214 
    215   .. ts:def:: ChallengeSetupRequest
    216 
    217     interface ChallengeSetupRequest {
    218       // If true, the given address should not be edited.
    219       // Defaults to 'false' if not specified.
    220       read_only?: boolean;
    221 
    222       // Optional, additional fields to pre-populate
    223       // the address to be validated.
    224       // The fields depend on the challenger type.
    225       [x: string]: any;
    226     }
    227 
    228 
    229   .. ts:def:: ChallengeSetupResponse
    230 
    231     interface ChallengeSetupResponse {
    232       // Nonce to use when constructing ``/authorize`` endpoint.
    233       nonce: string;
    234     }
    235 
    236 
    237 .. _challenger-login:
    238 
    239 -----
    240 Login
    241 -----
    242 
    243 .. http:get:: /authorize/$NONCE
    244 .. http:post:: /authorize/$NONCE
    245 
    246   This is the "authorization" endpoint of the OAuth 2.0 protocol.  This
    247   endpoint is used by the user-agent. It will return a form to enter the
    248   address.
    249 
    250   The NONCE is a unique value identifying the challenge, should be shown to
    251   the user so that they can recognize it when they receive the TAN code.
    252 
    253   Note that both for GET and POST requests the request arguments must
    254   be given in the URL and the body should be empty. We currently do NOT
    255   support using x-www-form-urlencoded arguments in the body, even for
    256   a POST.
    257 
    258   **Request:**
    259 
    260   :query response_type: Must be ``code``
    261   :query client_id: Identifier of the client.
    262   :query redirect_uri: URI-encoded redirection URI to use upon authorization.
    263   :query state: Arbitrary client state to associate with the request.
    264   :query scope: Not supported, any value is accepted.
    265   :query code_challenge: A string to enhance security using PKCE (available since **v3**).
    266   :query code_challenge_method: The method used for the code_challenge. Options are S256 (SHA-256) or plain (available since **v3**).
    267 
    268   **Response:**
    269 
    270   :http:statuscode:`200 OK`:
    271     The the response is
    272     a `ChallengeStatus`. Since protocol **v1**.
    273   :http:statuscode:`302 Found`:
    274     Returned when the client explicitly accepts ``text/html``
    275     returning a redirection to the WebUI.
    276     Since protocol **v1**.
    277   :http:statuscode:`400 Bad Request`:
    278     The request does not follow the spec.
    279     The response will include error
    280     code, hint and detail. Since protocol **v1**.
    281   :http:statuscode:`404 Not found`:
    282     The service is unaware of a matching challenge.
    283     The response will include error
    284     code, hint and detail. Since protocol **v1**.
    285   :http:statuscode:`406 Not Acceptable`:
    286     The client ask for "text/html" and the backend installation does
    287     not include the required HTML templates.
    288   :http:statuscode:`500 Internal Server Error`:
    289     Server is not able to respond due to internal problems.
    290     The response will include error
    291     code, hint and detail. Since protocol **v1**.
    292 
    293   .. ts:def:: ChallengeStatus
    294 
    295     interface ChallengeStatus {
    296 
    297       // indicates if the given address cannot be changed anymore, the
    298       // form should be read-only if set to true.
    299       fix_address: boolean;
    300 
    301       // form values from the previous submission if available, details depend
    302       // on the ``ADDRESS_TYPE``, should be used to pre-populate the form
    303       last_address?: Object;
    304 
    305       // is the challenge already solved?
    306       solved: boolean;
    307 
    308       // number of times the address can still be changed, may or may not be
    309       // shown to the user
    310       changes_left: Integer;
    311 
    312       // when we would re-transmit the challenge the next
    313       // time (at the earliest) if requested by the user
    314       // only present if challenge already created
    315       // @since **v2**
    316       retransmission_time: Timestamp;
    317 
    318       // how many times might the PIN still be retransmitted
    319       // only present if challenge already created
    320       // @since **v2**
    321       pin_transmissions_left?: Integer;
    322 
    323       // how many times might the user still try entering the PIN code
    324       // only present if challenge already created
    325       // @since **v2**
    326       auth_attempts_left?: Integer;
    327     }
    328 
    329 
    330 .. _challenger-challenge:
    331 
    332 ---------
    333 Challenge
    334 ---------
    335 
    336 .. http:post:: /challenge/$NONCE
    337 
    338   This endpoint is used by the user-agent to submit the address to which a
    339   challenge should be sent by the challenger service.
    340 
    341   **Request:**
    342 
    343   Body should use the mime-type "application/x-www-form-urlencoded".
    344   The posted form data must contain an object that follow the restrictions
    345   defined in :ref:`config <challenger-config>`.
    346 
    347   **Response:**
    348 
    349   :http:statuscode:`200 OK`:
    350     The response is `ChallengeResponse`. Since protocol **v2**.
    351   :http:statuscode:`400 Bad Request`:
    352     The request does not follow the spec.
    353     The response will include error
    354     code, hint and detail. Since protocol **v1**.
    355   :http:statuscode:`403 Forbidden`:
    356     The address being submitted differs from the previously
    357     submitted address but the validation process was set up
    358     as ``read_only`` and thus the address cannot be changed.
    359     Returned with
    360     ``TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_READ_ONLY``.
    361     Since protocol **v4**.
    362   :http:statuscode:`404 Not Found`:
    363     The service is unaware of a matching challenge.
    364     The response will include error
    365     code, hint and detail. Since protocol **v1**.
    366   :http:statuscode:`406 Not Acceptable`:
    367     The client ask for "text/html" and the backend installation does
    368     not include the required HTML templates.
    369   :http:statuscode:`429 Too Many Requests`:
    370     There have been too many attempts to request challenge
    371     transmissions for this $NONCE. The user-agent should
    372     wait and (eventually) request a fresh nonce to be set
    373     up by the client.
    374     Returned with ``TALER_EC_CHALLENGER_TOO_MANY_ATTEMPTS``.
    375     Since protocol **v2**.
    376   :http:statuscode:`500 Internal Server Error`:
    377     Server is not able to respond due to internal problems.
    378     The response will include error
    379     code, hint and detail. Since protocol **v1**.
    380   :http:statuscode:`502 Bad Gateway`:
    381     The challenger service failed to launch or communicate with
    382     its helper process for delivering the challenge (SMS, e-mail,
    383     postal mail).  Returned with
    384     ``TALER_EC_CHALLENGER_HELPER_EXEC_FAILED``.
    385 
    386   .. ts:def:: ChallengeResponse
    387 
    388     // Union discriminated by the "type" field.
    389     type ChallengeResponse = ChallengeRedirect | ChallengeCreateResponse
    390 
    391   .. ts:def:: ChallengeRedirect
    392 
    393     // @since **v2**
    394     interface ChallengeRedirect {
    395       // Union discriminator field.
    396       type: "completed";
    397 
    398       // challenge is completed, use should redirect here
    399       redirect_url: string;
    400     }
    401 
    402   .. ts:def:: ChallengeCreateResponse
    403 
    404    interface ChallengeCreateResponse {
    405       // Union discriminator field.
    406       type: "created"
    407 
    408       // how many more attempts are allowed, might be shown to the user,
    409       // highlighting might be appropriate for low values such as 1 or 2 (the
    410       // form will never be used if the value is zero)
    411       attempts_left: Integer;
    412 
    413       // the address that is being validated, might be shown or not
    414       address: Object;
    415 
    416       // true if we just retransmitted the challenge, false if we sent a
    417       // challenge recently and thus refused to transmit it again this time;
    418       // might make a useful hint to the user
    419       transmitted: boolean;
    420 
    421       // @deprecated in **v2**, use retransmission_time
    422       next_tx_time?: string;
    423 
    424       // when we would re-transmit the challenge the next
    425       // time (at the earliest) if requested by the user
    426       // @since **v2**
    427       retransmission_time: Timestamp;
    428     }
    429 
    430 
    431 .. _challenger-solve:
    432 
    433 -----
    434 Solve
    435 -----
    436 
    437 .. http:post:: /solve/$NONCE
    438 
    439   Used by the user-agent to submit an answer to the challenge.  If the answer
    440   is correct, the user will be redirected to the client's redirect URI,
    441   otherwise the user may be given another chance to complete the process.
    442 
    443   **Request:**
    444 
    445   Body should use the mime-type "application/x-www-form-urlencoded".
    446   The posted form data must contain a "pin" field.
    447 
    448   **Response:**
    449 
    450   :http:statuscode:`200 OK`:
    451     If the request ask for application/json the response is
    452     a `ChallengeSolveResponse`. Since protocol **v2**.
    453   :http:statuscode:`302 Found`:
    454     Only possible if request didn't ask for application/json. Since protocol **v2**.
    455     The user is redirected to the redirect URI of the client to pass the
    456     grant to the client.  The target will be the redirect URI specified
    457     by the client (during registration and again upon ``/authorize``),
    458     plus a ``code`` argument with the authorization code, and the
    459     ``state`` argument from the ``/authorize`` endpoint.
    460   :http:statuscode:`400 Bad Request`:
    461     The request does not follow the spec.
    462     The response will include error
    463     code, hint and detail. Since protocol **v1**.
    464   :http:statuscode:`403 Forbidden`:
    465     The response is `InvalidPinResponse`. Since protocol **v1**.
    466   :http:statuscode:`404 Not found`:
    467     The service is unaware of a matching challenge.
    468     The response will include error
    469     code, hint and detail. Since protocol **v1**.
    470   :http:statuscode:`429 Too Many Requests`:
    471     There have been too many attempts to solve the challenge
    472     for this address (and $NONCE). The user-agent should
    473     either try a different address (or wait and (eventually)
    474     request a fresh nonce to be set up by the client).
    475     The response will include error
    476     code, hint and detail. Since protocol **v2**.
    477   :http:statuscode:`500 Internal Server Error`:
    478     Server is not able to respond due to internal problems.
    479     The response will include error
    480     code, hint and detail. Since protocol **v1**.
    481 
    482   .. ts:def:: ChallengeSolveResponse
    483 
    484     // Union discriminated by the "type" field.
    485     type ChallengeSolveResponse = ChallengeRedirect | InvalidPinResponse;
    486 
    487   .. ts:def:: InvalidPinResponse
    488 
    489     interface InvalidPinResponse {
    490       // Union discriminator field.
    491       type: "pending";
    492 
    493       // numeric Taler error code, should be shown to indicate the error
    494       // compactly for reporting to developers
    495       code: Integer;
    496 
    497       // human-readable Taler error code, should be shown for the user to
    498       // understand the error
    499       hint: string;
    500 
    501       // how many times is the user still allowed to change the address;
    502       // if 0, the user should not be shown a link to jump to the
    503       // address entry form
    504       addresses_left: Integer;
    505 
    506       // how many times might the PIN still be retransmitted
    507       pin_transmissions_left: Integer;
    508 
    509       // how many times might the user still try entering the PIN code
    510       auth_attempts_left: Integer;
    511 
    512       // if true, the PIN was not even evaluated as the user previously
    513       // exhausted the number of attempts
    514       exhausted: boolean;
    515 
    516       // if true, the PIN was not even evaluated as no challenge was ever
    517       // issued (the user must have skipped the step of providing their
    518       // address first!)
    519       no_challenge: boolean;
    520     }
    521 
    522 .. _challenger-auth:
    523 
    524 ----
    525 Auth
    526 ----
    527 
    528 .. http:post:: /token
    529 
    530   This is the token endpoint of the OAuth 2.0 specification.
    531   This endpoint is used by the client to provide its authorization code,
    532   demonstrating that it has the right to learn a particular user's validated
    533   address.  In return, the challenger service returns the access token.
    534   Renewal is not supported.
    535 
    536   **Request:**
    537 
    538   The request must include an ``application/www-form-urlencoded`` body
    539   specifying the ``client_id``, ``redirect_uri``, ``client_secret``, ``code``
    540   and ``grant_type``.  The ``grant_type`` must be set to
    541   ``authorization_code``.  The ``redirect_uri`` must match the URI from
    542   ``/authorize``. The ``code`` must be the authorization code that ``/solve``
    543   returned to the user.  The ``client_id`` and ``client_secret`` must match
    544   the usual client credentials. Since protocol **v3**, ``code_verifier`` can also be included.
    545 
    546   **Response:**
    547 
    548   Error responses follow RFC 6749, section 5.2 with an "error" field in JSON,
    549   as well as also returning GNU Taler style error messages.
    550 
    551   :http:statuscode:`200 OK`:
    552     The body will be a `ChallengerAuthResponse`.
    553   :http:statuscode:`400 Bad Request`:
    554     A required POST field (``grant_type``, ``client_id``,
    555     ``client_secret``, ``code`` or ``redirect_uri``) is missing
    556     or malformed, or ``grant_type`` is not ``authorization_code``.
    557     Usually returned with ``TALER_EC_GENERIC_PARAMETER_MISSING``
    558     or ``TALER_EC_GENERIC_PARAMETER_MALFORMED``.
    559   :http:statuscode:`401 Unauthorized`:
    560     Authentication of the client failed.  Returned (per
    561     RFC 6749, section 5.2) when the client credentials are
    562     invalid, when the supplied ``code`` is malformed or does
    563     not match the validation, when the ``redirect_uri`` does
    564     not match the one registered with the client, or when the
    565     ``code_verifier`` does not match the saved
    566     ``code_challenge``.  Returned with
    567     ``TALER_EC_CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI``,
    568     ``TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE``,
    569     ``TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN`` or
    570     ``TALER_EC_CHALLENGER_GRANT_UNKNOWN``.
    571     PKCE-related rejections are since protocol **v3**.
    572   :http:statuscode:`404 Not found`:
    573     The service is unaware of a matching login process or client.
    574     Returned with error codes of
    575     ``TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKOWN``
    576   :http:statuscode:`409 Conflict`:
    577     A ``code`` was presented for a validation process for which
    578     the user has not (yet) submitted any address, so the token
    579     cannot be issued.  Returned with
    580     ``TALER_EC_CHALLENGER_MISSING_ADDRESS``.
    581   :http:statuscode:`500 Internal Server Error`:
    582     The challenger service encountered an internal error,
    583     for example a database failure or a failure of the SHA-256
    584     or Base64 helpers used for PKCE verification.
    585     Error codes used are:
    586     * ``TALER_EC_CHALLENGER_GENERIC_DB_FETCH_FAILED``
    587     * ``TALER_EC_CHALLENGER_GENERIC_DB_STORE_FAILED``
    588 
    589   **Details::**
    590 
    591   .. ts:def:: ChallengerAuthResponse
    592 
    593     interface ChallengerAuthResponse {
    594       // Token used to authenticate access in ``/info``.
    595       access_token: string;
    596 
    597       // Type of the access token.
    598       token_type: "Bearer";
    599 
    600       // Amount of time that an access token is valid (in seconds).
    601       expires_in: Integer;
    602 
    603     }
    604 
    605 
    606 .. _challenger-info:
    607 
    608 ----
    609 Info
    610 ----
    611 
    612 .. http:get:: /info
    613 
    614   This userinfo endpoint of the OAuth 2.0 specification.
    615   This endpoint is used by the client to obtain the user's validated address.
    616 
    617   **Request:**
    618 
    619   Must include the token returned to the client from the ``/token`` endpoint
    620   as a ``Bearer`` token in an ``Authorization`` header.
    621 
    622   **Response:**
    623 
    624   :http:statuscode:`200 OK`:
    625     The body contains the address as a `ChallengerInfoResponse`.
    626   :http:statuscode:`403 Forbidden`:
    627     The bearer token is missing or invalid (malformed).
    628   :http:statuscode:`404 Not found`:
    629     The bearer token is invalid (includes unknown or expired).
    630     Returned with ``TALER_EC_CHALLENGER_GRANT_UNKNOWN``.
    631   :http:statuscode:`500 Internal Server Error`:
    632     The challenger service encountered an internal error,
    633     typically a database failure.  Usually returned with
    634     ``TALER_EC_GENERIC_DB_FETCH_FAILED``.
    635 
    636   **Details::**
    637 
    638   .. ts:def:: ChallengerInfoResponse
    639 
    640     interface ChallengerInfoResponse {
    641 
    642       // Unique ID of the record within Challenger
    643       // (identifies the rowid of the token).
    644       id: Integer;
    645 
    646       // Address that was validated.
    647       // Key-value pairs, details depend on the
    648       // address_type.
    649       address: Object;
    650 
    651      // Type of the address.
    652       address_type: string;
    653 
    654       // How long do we consider the address to be
    655       // valid for this user.
    656       expires: Timestamp;
    657 
    658     }