commit d19219d874b881b3c7dee47ab727632b6d44d3ee
parent f7a7f584f1d6f8aeeb45fe1cf827635ff2553b67
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 2 Sep 2025 22:28:52 +0200
improve MFA spec
Diffstat:
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`: