summaryrefslogtreecommitdiff
path: root/src/kyclogic
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-11-03 14:44:25 +0100
committerChristian Grothoff <christian@grothoff.org>2023-11-03 14:44:25 +0100
commitee57a5f9c481555d0462012439a99778a2dbcbcb (patch)
tree223b26d17fdeecc19194ca661ac1b15fcf067f36 /src/kyclogic
parent082728f839e909453b60ba76396a9ae30f86a58f (diff)
downloadexchange-ee57a5f9c481555d0462012439a99778a2dbcbcb.tar.gz
exchange-ee57a5f9c481555d0462012439a99778a2dbcbcb.tar.bz2
exchange-ee57a5f9c481555d0462012439a99778a2dbcbcb.zip
add external converter logic for oauth2 plugin
Diffstat (limited to 'src/kyclogic')
-rw-r--r--src/kyclogic/Makefile.am5
-rw-r--r--src/kyclogic/kyclogic-oauth2.conf6
-rw-r--r--src/kyclogic/plugin_kyclogic_oauth2.c204
-rwxr-xr-x[-rw-r--r--]src/kyclogic/taler-exchange-kyc-oauth2-challenger.sh0
-rwxr-xr-x[-rw-r--r--]src/kyclogic/taler-exchange-kyc-oauth2-nda.sh0
-rwxr-xr-xsrc/kyclogic/taler-exchange-kyc-oauth2-test-converter.sh23
6 files changed, 117 insertions, 121 deletions
diff --git a/src/kyclogic/Makefile.am b/src/kyclogic/Makefile.am
index 91ec901e9..3e98a956f 100644
--- a/src/kyclogic/Makefile.am
+++ b/src/kyclogic/Makefile.am
@@ -16,7 +16,10 @@ pkgcfg_DATA = \
bin_SCRIPTS = \
taler-exchange-kyc-kycaid-converter.sh \
- taler-exchange-kyc-persona-converter.sh
+ taler-exchange-kyc-persona-converter.sh \
+ taler-exchange-kyc-oauth2-test-converter.sh \
+ taler-exchange-kyc-oauth2-challenger.sh \
+ taler-exchange-kyc-oauth2-nda.sh
EXTRA_DIST = \
$(pkgcfg_DATA) \
diff --git a/src/kyclogic/kyclogic-oauth2.conf b/src/kyclogic/kyclogic-oauth2.conf
index 61b38367f..57e1fc13a 100644
--- a/src/kyclogic/kyclogic-oauth2.conf
+++ b/src/kyclogic/kyclogic-oauth2.conf
@@ -29,7 +29,7 @@ KYC_OAUTH2_CLIENT_SECRET = password
# Mustach template that converts OAuth2.0 data about the user
# into GNU Taler standardized attribute data.
#
-# This is just an example, details will depend on the
-# provider!
+# This is just an example, you need to pick the right converter
+# for the provider!
#
-KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{last_name}}, {{first_name}}","phone":"{{phone}}"}" \ No newline at end of file
+KYC_OAUTH2_CONVERTER_HELPER = taler-exchange-kyc-oauth2-converter.sh
diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c
index 4bd0bbfef..5ef1330ad 100644
--- a/src/kyclogic/plugin_kyclogic_oauth2.c
+++ b/src/kyclogic/plugin_kyclogic_oauth2.c
@@ -113,10 +113,10 @@ struct TALER_KYCLOGIC_ProviderDetails
char *post_kyc_redirect_url;
/**
- * Template for converting user-data returned by
- * the provider into our KYC attribute data.
+ * Name of the program we use to convert outputs
+ * from Persona into our JSON inputs.
*/
- char *attribute_template;
+ char *conversion_binary;
/**
* Validity time for a successful KYC process.
@@ -188,6 +188,12 @@ struct TALER_KYCLOGIC_ProofHandle
struct MHD_Connection *connection;
/**
+ * Handle to an external process that converts the
+ * Persona response to our internal format.
+ */
+ struct TALER_JSON_ExternalConversion *ec;
+
+ /**
* Hash of the payto URI that this is about.
*/
struct TALER_PaytoHashP h_payto;
@@ -301,7 +307,7 @@ oauth2_unload_configuration (struct TALER_KYCLOGIC_ProviderDetails *pd)
GNUNET_free (pd->client_id);
GNUNET_free (pd->client_secret);
GNUNET_free (pd->post_kyc_redirect_url);
- GNUNET_free (pd->attribute_template);
+ GNUNET_free (pd->conversion_binary);
GNUNET_free (pd);
}
@@ -501,16 +507,14 @@ oauth2_load_configuration (void *cls,
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (ps->cfg,
provider_section_name,
- "KYC_OAUTH2_ATTRIBUTE_TEMPLATE",
- &s))
+ "KYC_OAUTH2_CONVERTER_HELPER",
+ &pd->conversion_binary))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
provider_section_name,
- "KYC_OAUTH2_ATTRIBUTE_TEMPLATE");
- }
- else
- {
- pd->attribute_template = s;
+ "KYC_OAUTH2_CONVERTER_HELPER");
+ oauth2_unload_configuration (pd);
+ return NULL;
}
return pd;
@@ -791,6 +795,11 @@ oauth2_initiate_cancel (struct TALER_KYCLOGIC_InitiateHandle *ih)
static void
oauth2_proof_cancel (struct TALER_KYCLOGIC_ProofHandle *ph)
{
+ if (NULL != ph->ec)
+ {
+ TALER_JSON_external_conversion_stop (ph->ec);
+ ph->ec = NULL;
+ }
if (NULL != ph->task)
{
GNUNET_SCHEDULER_cancel (ph->task);
@@ -907,93 +916,26 @@ handle_proof_error (struct TALER_KYCLOGIC_ProofHandle *ph,
/**
- * Convert user data returned by the provider into
- * standardized attribute data.
- *
- * @param pd our provider configuration
- * @param data user-data given by the provider
- * @return converted KYC attribute data object
- */
-static json_t *
-data2attributes (const struct TALER_KYCLOGIC_ProviderDetails *pd,
- const json_t *data)
-{
- json_t *ret;
- void *attr_data;
- size_t attr_size;
- int rv;
- json_error_t err;
-
- if (NULL == pd->attribute_template)
- return json_object ();
- if (0 !=
- (rv = TALER_TEMPLATING_fill (pd->attribute_template,
- data,
- &attr_data,
- &attr_size)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to convert KYC provider data to attributes: %d\n",
- rv);
- json_dumpf (data,
- stderr,
- JSON_INDENT (2));
- return NULL;
- }
- ret = json_loadb (attr_data,
- attr_size,
- JSON_REJECT_DUPLICATES,
- &err);
- GNUNET_free (attr_data);
- if (NULL == ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse converted KYC attributes as JSON: %s (at offset %d)\n",
- err.text,
- err.position);
- return NULL;
- }
- return ret;
-}
-
-
-/**
- * The request for @a ph succeeded (presumably).
- * Call continuation with the result.
+ * Type of a callback that receives a JSON @a result.
*
- * @param[in,out] ph request that succeeded
- * @param j reply from the server
+ * @param cls closure with a `struct TALER_KYCLOGIC_ProofHandle *`
+ * @param status_type how did the process die
+ * @param code termination status code from the process
+ * @param attr result some JSON result, NULL if we failed to get an JSON output
*/
static void
-parse_proof_success_reply (struct TALER_KYCLOGIC_ProofHandle *ph,
- const json_t *j)
+converted_proof_cb (void *cls,
+ enum GNUNET_OS_ProcessStatusType status_type,
+ unsigned long code,
+ const json_t *attr)
{
- // FIXME: this is not OAuth2.0, this is
- // already implementation-specific!
- // => move into helper shell script!
- const char *state;
- const json_t *data;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("status",
- &state),
- GNUNET_JSON_spec_object_const ("data",
- &data),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
- const char *emsg;
- unsigned int line;
-
- res = GNUNET_JSON_parse (j,
- spec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
+ struct TALER_KYCLOGIC_ProofHandle *ph = cls;
+
+ ph->ec = NULL;
+ if ( (NULL == attr) ||
+ (0 != code) )
{
GNUNET_break_op (0);
- json_dumpf (j,
- stderr,
- JSON_INDENT (2));
ph->status = TALER_KYCLOGIC_STATUS_PROVIDER_FAILED;
ph->response
= TALER_MHD_make_error (
@@ -1001,16 +943,11 @@ parse_proof_success_reply (struct TALER_KYCLOGIC_ProofHandle *ph,
"Unexpected response from KYC gateway: proof success must contain data and status");
ph->http_status
= MHD_HTTP_BAD_GATEWAY;
+ ph->task = GNUNET_SCHEDULER_add_now (&return_proof_response,
+ ph);
return;
}
- if (0 != strcasecmp (state,
- "success"))
- {
- GNUNET_break_op (0);
- handle_proof_error (ph,
- j);
- return;
- }
+
{
const char *id;
struct GNUNET_JSON_Specification ispec[] = {
@@ -1018,15 +955,18 @@ parse_proof_success_reply (struct TALER_KYCLOGIC_ProofHandle *ph,
&id),
GNUNET_JSON_spec_end ()
};
+ enum GNUNET_GenericReturnValue res;
+ const char *emsg;
+ unsigned int line;
- res = GNUNET_JSON_parse (data,
+ res = GNUNET_JSON_parse (attr,
ispec,
&emsg,
&line);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
- json_dumpf (data,
+ json_dumpf (attr,
stderr,
JSON_INDENT (2));
ph->status = TALER_KYCLOGIC_STATUS_PROVIDER_FAILED;
@@ -1038,21 +978,51 @@ parse_proof_success_reply (struct TALER_KYCLOGIC_ProofHandle *ph,
= MHD_HTTP_BAD_GATEWAY;
return;
}
- ph->status = TALER_KYCLOGIC_STATUS_SUCCESS;
- ph->response = MHD_create_response_from_buffer (0,
- "",
- MHD_RESPMEM_PERSISTENT);
- GNUNET_assert (NULL != ph->response);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (
- ph->response,
- MHD_HTTP_HEADER_LOCATION,
- ph->pd->post_kyc_redirect_url));
- ph->http_status = MHD_HTTP_SEE_OTHER;
ph->provider_user_id = GNUNET_strdup (id);
}
- ph->attributes = data2attributes (ph->pd,
- data);
+ ph->status = TALER_KYCLOGIC_STATUS_SUCCESS;
+ ph->response = MHD_create_response_from_buffer (0,
+ "",
+ MHD_RESPMEM_PERSISTENT);
+ GNUNET_assert (NULL != ph->response);
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (
+ ph->response,
+ MHD_HTTP_HEADER_LOCATION,
+ ph->pd->post_kyc_redirect_url));
+ ph->http_status = MHD_HTTP_SEE_OTHER;
+ ph->attributes = json_incref ((json_t *) attr);
+ ph->task = GNUNET_SCHEDULER_add_now (&return_proof_response,
+ ph);
+}
+
+
+/**
+ * The request for @a ph succeeded (presumably).
+ * Call continuation with the result.
+ *
+ * @param[in,out] ph request that succeeded
+ * @param j reply from the server
+ */
+static void
+parse_proof_success_reply (struct TALER_KYCLOGIC_ProofHandle *ph,
+ const json_t *j)
+{
+ const struct TALER_KYCLOGIC_ProviderDetails *pd = ph->pd;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Calling converter `%s' with JSON\n",
+ pd->conversion_binary);
+ json_dumpf (j,
+ stderr,
+ JSON_INDENT (2));
+ ph->ec = TALER_JSON_external_conversion_start (
+ j,
+ &converted_proof_cb,
+ ph,
+ pd->conversion_binary,
+ pd->conversion_binary,
+ NULL);
}
@@ -1079,7 +1049,7 @@ handle_curl_proof_finished (void *cls,
case MHD_HTTP_OK:
parse_proof_success_reply (ph,
j);
- break;
+ return;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"OAuth2.0 info URL returned HTTP status %u\n",
diff --git a/src/kyclogic/taler-exchange-kyc-oauth2-challenger.sh b/src/kyclogic/taler-exchange-kyc-oauth2-challenger.sh
index 667dce5e7..667dce5e7 100644..100755
--- a/src/kyclogic/taler-exchange-kyc-oauth2-challenger.sh
+++ b/src/kyclogic/taler-exchange-kyc-oauth2-challenger.sh
diff --git a/src/kyclogic/taler-exchange-kyc-oauth2-nda.sh b/src/kyclogic/taler-exchange-kyc-oauth2-nda.sh
index 61c743c82..61c743c82 100644..100755
--- a/src/kyclogic/taler-exchange-kyc-oauth2-nda.sh
+++ b/src/kyclogic/taler-exchange-kyc-oauth2-nda.sh
diff --git a/src/kyclogic/taler-exchange-kyc-oauth2-test-converter.sh b/src/kyclogic/taler-exchange-kyc-oauth2-test-converter.sh
new file mode 100755
index 000000000..06b8ed1ab
--- /dev/null
+++ b/src/kyclogic/taler-exchange-kyc-oauth2-test-converter.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is in the public domain.
+#
+# This code converts (some of) the JSON output from
+# Challenger into the GNU Taler
+# specific KYC attribute data (again in JSON format).
+#
+
+# Die if anything goes wrong.
+set -eu
+
+
+# First, extract everything from stdin.
+J=$(jq '{"first":.first_name,"last".last_name"}')
+
+# Next, combine some fields into larger values.
+FULLNAME=$(echo "$J" | jq -r '[.first,.last]|join(" ")')
+
+jq \
+ --arg full_name "${FULLNAME}" \
+ '{$full_name}'
+
+exit 0