taler-docs

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

commit d19219d874b881b3c7dee47ab727632b6d44d3ee
parent f7a7f584f1d6f8aeeb45fe1cf827635ff2553b67
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue,  2 Sep 2025 22:28:52 +0200

improve MFA spec

Diffstat:
Mcore/api-corebank.rst | 13++++++++++---
Mcore/api-merchant.rst | 56++++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/core/api-corebank.rst b/core/api-corebank.rst @@ -224,7 +224,7 @@ The user ``admin`` is a special, hard-coded username. Some requests require the Deprecated since **v5**. Use *limit* instead. :query start: *Optional.* Deprecated since **v5**. Use *offset* instead. - + **Response:** :http:statuscode:`200 OK`: @@ -786,7 +786,7 @@ Account Management // Is 2FA enabled and what channel is used for challenges? tan_channel?: TanChannel; - + // Current status of the account // active: the account can be used // locked: the account can be used but cannot create new tokens @@ -802,7 +802,7 @@ Account Management // @since **v9** conversion_rate_class_id?: Integer; } - + Transactions ------------ @@ -1578,6 +1578,10 @@ Conversion rate class This endpoints is not authenticated for token creation challenges. + **Request:** + + The request body must be empty. + **Response:** :http:statuscode:`200 OK`: @@ -1602,6 +1606,9 @@ Conversion rate class tan_channel: TanChannel; // Info of the last successful transmission of the TAN challenge. + // Hint to show to the user as to where the challenge was + // sent or what to use to solve the challenge. May not + // contain the full address for privacy. tan_info: string; } diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -260,6 +260,43 @@ such as the implemented version of the protocol and the currency used. Two Factor Auth --------------- +202 Challenge Responses +^^^^^^^^^^^^^^^^^^^^^^^ + +Various APIs generate ``202 Accepted`` HTTP status codes when multi-factor +authentication (MFA) is required. In this case, the response will be a +`ChallengeResponse`. In these cases, the client must first request and solve +one or more challenges before repeating the request. When repeating the +request, they must include a list of comma-separated challenge IDs of the +solved challenges in an ``Taler-Challenge-Ids`` HTTP header. The body must +remain absolutely unchanged. + + .. note:: + + If all allowed attempts to solve the MFA challenge(s) fail, the endpoint + may start to return ``403 Forbidden`` until the issued challenges expire, + preventing the request from being completed for a while. In this case, + repeating the request with a different body may still be allowed! + + .. ts:def:: ChallengeResponse + + // @since v21 + interface ChallengeResponse { + // List of challenge IDs that must be solved before the + // client may proceed. + challenges: string[]; + + // True if **all** challenges must be solved (AND), false if + // it is sufficient to solve one of them (OR). + combi_and: bool; + + } + + + +Requesting challenges +^^^^^^^^^^^^^^^^^^^^^ + .. http:post:: [/instances/$INSTANCE]/challenge/$CHALLENGE_ID Send TAN code for the ``CHALLENGE_ID`` challenge. @@ -284,9 +321,13 @@ Two Factor Auth :http:statuscode:`404 Not Found`: The challenge was not found. Returned with ``TALER_EC_MERCHANT_TAN_CHALLENGE_UNKNOWN``. + :http:statuscode:`410 Gone`: + The challenge was already solved. + Returned with ``TALER_EC_MERCHANT_TAN_CHALLENGE_SOLVED``. :http:statuscode:`429 Too many requests`: Too many challenges are active right now, you must wait or confirm current challenges. + Returned with ``TALER_EC_MERCHANT_TAN_TOO_EARLY``. :http:statuscode:`502 Bad Gateway`: TAN transmition via ``tan_channel`` failed. Returned with ``TALER_EC_MERCHANT_MFA_HELPER_EXEC_FAILED``. @@ -307,6 +348,9 @@ Two Factor Auth } +Solving challenges +^^^^^^^^^^^^^^^^^^ + .. http:post:: [/instances/$INSTANCE]/challenge/$CHALLENGE_ID/confirm Solves the ``CHALLENGE_ID`` challenge and allows performing the protected operation. @@ -314,7 +358,7 @@ Two Factor Auth @since **v21** When the challenge is confirmed, you can call the protected endpoint again - with ``CHALLENGE_ID`` in the ``X-Challenge-Id`` HTTP header and the + with ``CHALLENGE_ID`` in the ``Taler-Challenge-Ids`` HTTP header and the original request body. This endpoints is not authenticated for token creation challenges. Too many @@ -337,17 +381,13 @@ Two Factor Auth **Response:** :http:statuscode:`204 No Content`: - The challenge is confirmed. + The challenge was solved. :http:statuscode:`404 Not Found`: The challenge was not found. Returned with ``TALER_EC_MERCHANT_TAN_CHALLENGE_UNKNOWN``. :http:statuscode:`409 Conflict`: Wrong TAN, returned with an error code of ``TALER_EC_MERCHANT_TAN_CHALLENGE_FAILED``. - :http:statuscode:`410 Gone`: - The challenge expired (but is still remembered by the merchant). - Returned with ``TALER_EC_MERCHANT_TAN_CHALLENGE_EXPIRED``. - Note that this status code is not guaranteed, you may also get a 404. :http:statuscode:`429 Too many requests`: Too many failed confirmation attempts, a new TAN must be requested. Returned with ``TALER_EC_MERCHANT_TAN_TOO_MANY_ATTEMPTS``. @@ -1239,7 +1279,7 @@ Setting up instances Same as ``/management/instances/$INSTANCE/auth`` it will update the password of the instance but without requiring the current password. On the first call it will validate the request and return the challenge id with a 202 response. Once the challenge is solved the - request needs to be repeated with the X-Challenge-Id header. Since protocol **v21** + request needs to be repeated with the ``Taler-Challenge-Ids`` header. Since protocol **v21** **Request** the request must be an `InstanceAuthConfigurationMessage`. @@ -1344,7 +1384,7 @@ Setting up instances **Response:** :http:statuscode:`202 Accepted`: - 2FA is required for this operation. This returns the `Challenge` response. @since **v21** + 2FA is required for this operation. This returns the `ChallengeResponse` response. @since **v21** :http:statuscode:`204 No content`: The backend has successfully created the instance. :http:statuscode:`404 Not found`: