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:
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);
}