summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/sphinx/reducer.rst44
-rw-r--r--src/authorization/anastasis_authorization_plugin_iban.c32
-rw-r--r--src/authorization/authorization-iban-messages.json4
-rw-r--r--src/reducer/anastasis_api_recovery_redux.c84
4 files changed, 140 insertions, 24 deletions
diff --git a/doc/sphinx/reducer.rst b/doc/sphinx/reducer.rst
index 68df5b1..dcfc522 100644
--- a/doc/sphinx/reducer.rst
+++ b/doc/sphinx/reducer.rst
@@ -1591,7 +1591,7 @@ that applications must all handle. States other than ``solved`` are:
}
}
- - **rate-limit-exceeded**:
+ - **rate-limit-exceeded**: This indicates that the user has made too many invalid attempts in too short an amount of time.
.. code-block:: json
@@ -1609,7 +1609,7 @@ that applications must all handle. States other than ``solved`` are:
}
}
- - **authentication-timeout**:
+ - **authentication-timeout**: This indicates that the challenge is awaiting for some external authentication process to complete. The application should ``poll`` for it to complete, or proceed with selecting other challenges.
.. code-block:: json
@@ -1627,6 +1627,46 @@ that applications must all handle. States other than ``solved`` are:
}
}
+ - **authentication-instructions**: This indicates that the challenge requires the user to perform some authetnication method-specific actions. Details about what the user should do are provided.
+
+ .. code-block:: json
+
+ {
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": {
+ "...": "..."
+ }
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": {
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
+ "state": "external-instructions",
+ "method": "iban",
+ "details": {
+ "...": "..."
+ }
+ }
+ }
+ }
+
+ The specific instructions depend on the ``method``.
+ They include:
+
+ - **iban**: The user must perform a wire transfer from their account to the Anastasis provider.
+
+ .. code-block:: json
+
+ {
+ "challenge_amount": "EUR:1",
+ "credit_iban": "DE12345789000",
+ "business_name": "Data Loss Incorporated",
+ "wire_transfer_subject": 987654321
+ }
+
+ Note that the actual wire transfer subject must contain both
+ the numeric ``wire_transfer_subject`` given above as well as
+ the string ``Anastasis``. Thus, when generating human-readable
+ instructions from the above, the display output should be
+ ``Anastasis 987654321``.
**poll:**
diff --git a/src/authorization/anastasis_authorization_plugin_iban.c b/src/authorization/anastasis_authorization_plugin_iban.c
index 4f43d3f..ef11b88 100644
--- a/src/authorization/anastasis_authorization_plugin_iban.c
+++ b/src/authorization/anastasis_authorization_plugin_iban.c
@@ -319,14 +319,6 @@ respond_with_challenge (struct ANASTASIS_AUTHORIZATION_State *as,
/* Build HTTP response */
{
struct MHD_Response *resp;
- const char *end;
- size_t slen;
-
- slen = strlen (as->iban_number);
- if (slen > 4)
- end = &as->iban_number[slen - 4];
- else
- end = &as->iban_number[slen / 2];
if (TALER_MHD_xmime_matches (mime,
"application/json"))
@@ -334,16 +326,17 @@ respond_with_challenge (struct ANASTASIS_AUTHORIZATION_State *as,
resp = TALER_MHD_MAKE_JSON_PACK (
GNUNET_JSON_pack_string ("method",
"iban"),
- TALER_JSON_pack_amount ("challenge_amount",
- &ctx->expected_amount),
- GNUNET_JSON_pack_string ("credit_iban",
- ctx->business_iban),
- GNUNET_JSON_pack_string ("business_name",
- ctx->business_name),
- GNUNET_JSON_pack_uint64 ("wire_transfer_subject",
- as->code),
- GNUNET_JSON_pack_string ("debit_account_hint",
- end));
+ GNUNET_JSON_pack_object_steal (
+ "details",
+ GNUNET_JSON_PACK (
+ TALER_JSON_pack_amount ("challenge_amount",
+ &ctx->expected_amount),
+ GNUNET_JSON_pack_string ("credit_iban",
+ ctx->business_iban),
+ GNUNET_JSON_pack_string ("business_name",
+ ctx->business_name),
+ GNUNET_JSON_pack_uint64 ("wire_transfer_subject",
+ as->code))));
}
else
{
@@ -357,8 +350,7 @@ respond_with_challenge (struct ANASTASIS_AUTHORIZATION_State *as,
TALER_amount2s (&ctx->expected_amount),
ctx->business_name,
ctx->business_iban,
- (unsigned long long) as->code,
- end);
+ (unsigned long long) as->code);
resp = MHD_create_response_from_buffer (reply_len,
reply,
MHD_RESPMEM_MUST_COPY);
diff --git a/src/authorization/authorization-iban-messages.json b/src/authorization/authorization-iban-messages.json
index 8c6295b..9575856 100644
--- a/src/authorization/authorization-iban-messages.json
+++ b/src/authorization/authorization-iban-messages.json
@@ -1,6 +1,6 @@
{
- "instructions" : "To authorize recovery, wire %s to %s at %s using a wire transfer subject of %llu from your bank account ending with %s",
+ "instructions" : "To authorize recovery, wire %s to %s at %s using a wire transfer subject of 'Anastasis %llu' from your bank account",
"instructions_i18n" : {
- "en_EN" : "To authorize recovery, wire %s to %s at %s using a wire transfer subject of %llu from your bank account ending with %s"
+ "en_EN" : "To authorize recovery, wire %s to %s at %s using a wire transfer subject of 'Anastasis %llu' from your bank account"
}
}
diff --git a/src/reducer/anastasis_api_recovery_redux.c b/src/reducer/anastasis_api_recovery_redux.c
index 95632cc..c549d35 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -708,6 +708,90 @@ answer_feedback_cb (
sctx->state);
sctx_free (sctx);
return;
+
+ case ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS:
+ {
+ json_t *body = NULL;
+ const char *mime;
+
+ mime = csr->details.open_challenge.content_type;
+ if (0 == strcasecmp (mime,
+ "application/json"))
+ {
+ body = json_loadb (csr->details.open_challenge.body,
+ csr->details.open_challenge.body_size,
+ JSON_REJECT_DUPLICATES,
+ NULL);
+ GNUNET_break_op (NULL != body);
+ }
+ if (NULL == body)
+ {
+ json_t *err;
+
+ err = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("state",
+ "server-failure"),
+ GNUNET_JSON_pack_uint64 ("error_code",
+ TALER_EC_GENERIC_INVALID_RESPONSE));
+ GNUNET_assert (0 ==
+ json_object_set_new (feedback,
+ uuid,
+ err));
+ }
+ else
+ {
+ const char *method;
+ json_t *details;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("method",
+ &method),
+ GNUNET_JSON_spec_json ("details",
+ &details),
+ GNUNET_JSON_spec_end ()
+ };
+ json_t *reply;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (body,
+ spec,
+ NULL, NULL))
+ {
+ json_t *err;
+
+ GNUNET_break_op (0);
+ err = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("state",
+ "server-failure"),
+ GNUNET_JSON_pack_uint64 ("error_code",
+ TALER_EC_GENERIC_REPLY_MALFORMED));
+ GNUNET_assert (0 ==
+ json_object_set_new (feedback,
+ uuid,
+ err));
+ return;
+ }
+
+ reply = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("state",
+ "external-instructions"),
+ GNUNET_JSON_pack_string ("method",
+ method),
+ GNUNET_JSON_pack_object_incref ("details",
+ details));
+ GNUNET_JSON_parse_free (spec);
+ GNUNET_assert (0 ==
+ json_object_set_new (feedback,
+ uuid,
+ reply));
+ }
+ }
+ set_state (sctx->state,
+ ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING);
+ sctx->cb (sctx->cb_cls,
+ TALER_EC_NONE,
+ sctx->state);
+ sctx_free (sctx);
+ return;
}
GNUNET_break (0);
ANASTASIS_redux_fail_ (sctx->cb,