merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit ac8357c5a6a45c114214395a1684dd306ade1c10
parent cde31c5f6f9e10f2c40303eb1029f9aa5368ea48
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 14 Oct 2025 21:36:26 +0200

add logic to create login token on instance creation (#10498)

Diffstat:
Mconfigure.ac | 4++--
Msrc/backend/taler-merchant-httpd_private-post-instances.c | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -329,12 +329,12 @@ AS_CASE([$with_exchange], CPPFLAGS="-I$with_exchange/include $CPPFLAGS $POSTGRESQL_CPPFLAGS"]) AC_CHECK_HEADERS([taler/taler_mhd_lib.h], - [AC_CHECK_LIB([talermhd], [TALER_MHD_listen_bind], libtalermhd=1)]) + [AC_CHECK_LIB([talermhd], [TALER_MHD_parse_request_arg_rel_time], libtalermhd=1)]) AM_CONDITIONAL(HAVE_TALERMHD, test x$libtalermhd = x1) AS_IF([test $libtalermhd != 1], [AC_MSG_ERROR([[ *** -*** You need libtalermhd >= 1.1.0 (API v6) to build this program. +*** You need libtalermhd >= 1.1.0 (API v8) to build this program. *** This library is part of the GNU Taler exchange, available at *** https://taler.net *** ]])]) diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -44,6 +44,8 @@ * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] hc context with further information about the request + * @param login_token_expiration set to how long a login token validity + * should be, use zero if no login token should be created * @param validation_needed true if self-provisioned and * email/phone registration is required before the * instance can become fully active @@ -53,6 +55,7 @@ static MHD_RESULT post_instances (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc, + struct GNUNET_TIME_Relative login_token_expiration, bool validation_needed) { struct TALER_MERCHANTDB_InstanceSettings is = { 0 }; @@ -446,11 +449,76 @@ retry: TMH_reload_instances (mi->settings.id); } GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); + if (GNUNET_TIME_relative_is_zero (login_token_expiration)) + { + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); + } + + { + struct TALER_MERCHANTDB_LoginTokenP btoken; + enum TMH_AuthScope iscope = TMH_AS_REFRESHABLE | TMH_AS_SPA; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Timestamp expiration_time; + bool refreshable = true; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &btoken, + sizeof (btoken)); + expiration_time + = GNUNET_TIME_relative_to_timestamp (login_token_expiration); + qs = TMH_db->insert_login_token (TMH_db->cls, + is.id, + &btoken, + GNUNET_TIME_timestamp_get (), + expiration_time, + iscope, + "login token from instance creation"); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); + return TALER_MHD_reply_with_ec (connection, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_login_token"); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } + + { + char *tok; + MHD_RESULT ret; + char *val; + + val = GNUNET_STRINGS_data_to_string_alloc (&btoken, + sizeof (btoken)); + GNUNET_asprintf (&tok, + RFC_8959_PREFIX "%s", + val); + GNUNET_free (val); + ret = TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_string ("access_token", + tok), + GNUNET_JSON_pack_string ("token", + tok), + GNUNET_JSON_pack_string ("scope", + TMH_get_name_by_scope (iscope, + &refreshable)), + GNUNET_JSON_pack_bool ("refreshable", + refreshable), + GNUNET_JSON_pack_timestamp ("expiration", + expiration_time)); + GNUNET_free (tok); + return ret; + } + } } @@ -470,6 +538,7 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, return post_instances (rh, connection, hc, + GNUNET_TIME_UNIT_ZERO, false); } @@ -488,6 +557,11 @@ TMH_public_post_instances (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { + struct GNUNET_TIME_Relative expiration; + + TALER_MHD_parse_request_rel_time (connection, + "token_validity_ms", + &expiration); if (GNUNET_YES != TMH_have_self_provisioning) { @@ -501,6 +575,7 @@ TMH_public_post_instances (const struct TMH_RequestHandler *rh, return post_instances (rh, connection, hc, + expiration, TEH_TCS_NONE != TEH_mandatory_tan_channels); }