From 5b3ded24a329d25b77372f17d75ff6b3d68bfa5d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 19 Aug 2021 15:11:17 +0200 Subject: document reducer return values for IBAN auth --- doc/sphinx/reducer.rst | 44 +++++++++++- .../anastasis_authorization_plugin_iban.c | 32 ++++----- src/authorization/authorization-iban-messages.json | 4 +- src/reducer/anastasis_api_recovery_redux.c | 84 ++++++++++++++++++++++ 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, -- cgit v1.2.3