gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: add logic to oauth2 plugin to us


From: gnunet
Subject: [taler-exchange] branch master updated: add logic to oauth2 plugin to use /setup endpoint when configured
Date: Sat, 13 May 2023 17:06:24 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new c9ed524b add logic to oauth2 plugin to use /setup endpoint when 
configured
c9ed524b is described below

commit c9ed524bc32beb7f5e8be5eeed077e54b81cf4df
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat May 13 17:06:21 2023 +0200

    add logic to oauth2 plugin to use /setup endpoint when configured
---
 contrib/gana                          |   2 +-
 src/kyclogic/kyclogic-oauth2.conf     |   6 +-
 src/kyclogic/plugin_kyclogic_oauth2.c | 229 ++++++++++++++++++++++++++++++----
 src/testing/test_kyc_api.conf         |   4 +-
 4 files changed, 209 insertions(+), 32 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 85736484..e50e3767 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 85736484cb0da26aded705ebb1e944e8bb1b8504
+Subproject commit e50e37672fae7983fb5e934cd1d381b92648f7b6
diff --git a/src/kyclogic/kyclogic-oauth2.conf 
b/src/kyclogic/kyclogic-oauth2.conf
index 6f83c0e4..61b38367 100644
--- a/src/kyclogic/kyclogic-oauth2.conf
+++ b/src/kyclogic/kyclogic-oauth2.conf
@@ -13,11 +13,11 @@ PROVIDED_CHECKS = EXAMPLE_DO_NOT_USE
 KYC_OAUTH2_VALIDITY = forever
 
 # URL where we initiate the user's login process
-KYC_OAUTH2_LOGIN_URL = http://kyc.example.com/login
+KYC_OAUTH2_AUTHORIZE_URL = https://kyc.example.com/authorize
 # URL where we send the user's authentication information
-KYC_OAUTH2_AUTH_URL = http://kyc.example.com/auth
+KYC_OAUTH2_TOKEN_URL = https://kyc.example.com/token
 # URL of the user info access point.
-KYC_OAUTH2_INFO_URL = http://kyc.example.com/info
+KYC_OAUTH2_INFO_URL = https://kyc.example.com/info
 
 # Where does the client get redirected upon completion?
 KYC_OAUTH2_POST_URL = http://example.com/thank-you
diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c 
b/src/kyclogic/plugin_kyclogic_oauth2.c
index c72b04b7..e7350f01 100644
--- a/src/kyclogic/plugin_kyclogic_oauth2.c
+++ b/src/kyclogic/plugin_kyclogic_oauth2.c
@@ -1,6 +1,6 @@
 /*
   This file is part of GNU Taler
-  Copyright (C) 2022 Taler Systems SA
+  Copyright (C) 2022-2023 Taler Systems SA
 
   Taler is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -74,16 +74,22 @@ struct TALER_KYCLOGIC_ProviderDetails
    */
   char *section;
 
+  /**
+   * URL of the Challenger ``/setup`` endpoint for
+   * approving address validations. NULL if not used.
+   */
+  char *setup_url;
+
   /**
    * URL of the OAuth2.0 endpoint for KYC checks.
-   * (token/auth)
    */
-  char *auth_url;
+  char *authorize_url;
 
   /**
    * URL of the OAuth2.0 endpoint for KYC checks.
+   * (token/auth)
    */
-  char *login_url;
+  char *token_url;
 
   /**
    * URL of the user info access endpoint.
@@ -147,6 +153,11 @@ struct TALER_KYCLOGIC_InitiateHandle
    */
   struct GNUNET_SCHEDULER_Task *task;
 
+  /**
+   * Handle for the OAuth 2.0 setup request.
+   */
+  struct GNUNET_CURL_Job *job;
+
   /**
    * Continuation to call.
    */
@@ -283,8 +294,9 @@ static void
 oauth2_unload_configuration (struct TALER_KYCLOGIC_ProviderDetails *pd)
 {
   GNUNET_free (pd->section);
-  GNUNET_free (pd->auth_url);
-  GNUNET_free (pd->login_url);
+  GNUNET_free (pd->token_url);
+  GNUNET_free (pd->setup_url);
+  GNUNET_free (pd->authorize_url);
   GNUNET_free (pd->info_url);
   GNUNET_free (pd->client_id);
   GNUNET_free (pd->client_secret);
@@ -327,12 +339,12 @@ oauth2_load_configuration (void *cls,
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (ps->cfg,
                                              provider_section_name,
-                                             "KYC_OAUTH2_AUTH_URL",
+                                             "KYC_OAUTH2_TOKEN_URL",
                                              &s))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                provider_section_name,
-                               "KYC_OAUTH2_AUTH_URL");
+                               "KYC_OAUTH2_TOKEN_URL");
     oauth2_unload_configuration (pd);
     return NULL;
   }
@@ -346,23 +358,23 @@ oauth2_load_configuration (void *cls,
   {
     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
                                provider_section_name,
-                               "KYC_OAUTH2_AUTH_URL",
+                               "KYC_OAUTH2_TOKEN_URL",
                                "not a valid URL");
     GNUNET_free (s);
     oauth2_unload_configuration (pd);
     return NULL;
   }
-  pd->auth_url = s;
+  pd->token_url = s;
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (ps->cfg,
                                              provider_section_name,
-                                             "KYC_OAUTH2_LOGIN_URL",
+                                             "KYC_OAUTH2_AUTHORIZE_URL",
                                              &s))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                provider_section_name,
-                               "KYC_OAUTH2_LOGIN_URL");
+                               "KYC_OAUTH2_AUTHORIZE_URL");
     oauth2_unload_configuration (pd);
     return NULL;
   }
@@ -376,13 +388,41 @@ oauth2_load_configuration (void *cls,
   {
     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
                                provider_section_name,
-                               "KYC_OAUTH2_LOGIN_URL",
+                               "KYC_OAUTH2_AUTHORIZE_URL",
                                "not a valid URL");
     oauth2_unload_configuration (pd);
     GNUNET_free (s);
     return NULL;
   }
-  pd->login_url = s;
+  if (NULL != strchr (s, '#'))
+  {
+    const char *extra = strchr (s, '#');
+    const char *slash = strrchr (s, '/');
+
+    if ( (0 != strcmp (extra,
+                       "#setup")) ||
+         (NULL == slash) )
+    {
+      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                                 provider_section_name,
+                                 "KYC_OAUTH2_AUTHORIZE_URL",
+                                 "not a valid authorze URL (bad fragment)");
+      oauth2_unload_configuration (pd);
+      GNUNET_free (s);
+      return NULL;
+    }
+    pd->authorize_url = GNUNET_strndup (s,
+                                        extra - s);
+    GNUNET_asprintf (&pd->setup_url,
+                     "%.*s/setup",
+                     (int) (slash - s),
+                     s);
+    GNUNET_free (s);
+  }
+  else
+  {
+    pd->authorize_url = s;
+  }
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (ps->cfg,
@@ -480,19 +520,20 @@ oauth2_load_configuration (void *cls,
  * how to begin the OAuth2.0 checking process to
  * the client.
  *
- * @param cls a `struct TALER_KYCLOGIC_InitiateHandle *`
+ * @param ih process to redirect for
+ * @param authorize_url authorization URL to use
  */
 static void
-initiate_task (void *cls)
+initiate_with_url (struct TALER_KYCLOGIC_InitiateHandle *ih,
+                   const char *authorize_url)
 {
-  struct TALER_KYCLOGIC_InitiateHandle *ih = cls;
+
   const struct TALER_KYCLOGIC_ProviderDetails *pd = ih->pd;
   struct PluginState *ps = pd->ps;
   char *hps;
   char *url;
   char legi_s[42];
 
-  ih->task = NULL;
   GNUNET_snprintf (legi_s,
                    sizeof (legi_s),
                    "%llu",
@@ -515,16 +556,11 @@ initiate_task (void *cls)
     }
     GNUNET_asprintf (&url,
                      "%s?response_type=code&client_id=%s&redirect_uri=%s",
-                     pd->login_url,
+                     authorize_url,
                      pd->client_id,
                      redirect_uri_encoded);
     GNUNET_free (redirect_uri_encoded);
   }
-  /* FIXME-API: why do we *redirect* the client here,
-     instead of making the HTTP request *ourselves*
-     and forwarding the response? This prevents us
-     from using authentication on initiation,
-     (which is desirable for challenger!) */
   ih->cb (ih->cb_cls,
           TALER_EC_NONE,
           url,
@@ -537,6 +573,142 @@ initiate_task (void *cls)
 }
 
 
+/**
+ * After we are done with the CURL interaction we
+ * need to update our database state with the information
+ * retrieved.
+ *
+ * @param cls a `struct TALER_KYCLOGIC_InitiateHandle *`
+ * @param response_code HTTP response code from server, 0 on hard error
+ * @param response in JSON, NULL if response was not in JSON format
+ */
+static void
+handle_curl_setup_finished (void *cls,
+                            long response_code,
+                            const void *response)
+{
+  struct TALER_KYCLOGIC_InitiateHandle *ih = cls;
+  const struct TALER_KYCLOGIC_ProviderDetails *pd = ih->pd;
+  const json_t *j = response;
+
+  ih->job = NULL;
+  switch (response_code)
+  {
+  case MHD_HTTP_OK:
+    {
+      const char *nonce;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_string ("nonce",
+                                 &nonce),
+        GNUNET_JSON_spec_end ()
+      };
+      enum GNUNET_GenericReturnValue res;
+      const char *emsg;
+      unsigned int line;
+      char *url;
+
+      res = GNUNET_JSON_parse (j,
+                               spec,
+                               &emsg,
+                               &line);
+      if (GNUNET_OK != res)
+      {
+        GNUNET_break_op (0);
+        json_dumpf (j,
+                    stderr,
+                    JSON_INDENT (2));
+        ih->cb (ih->cb_cls,
+                TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+                NULL,
+                NULL,
+                NULL,
+                "Unexpected response from KYC gateway: setup must return a 
nonce");
+        GNUNET_free (ih);
+        return;
+      }
+      GNUNET_asprintf (&url,
+                       "%s/%s",
+                       pd->setup_url,
+                       nonce);
+      initiate_with_url (ih,
+                         url);
+      GNUNET_free (url);
+      return;
+    }
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "/setup URL returned HTTP status %u\n",
+                (unsigned int) response_code);
+    ih->cb (ih->cb_cls,
+            TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+            NULL,
+            NULL,
+            NULL,
+            "/setup request to OAuth 2.0 backend returned unexpected HTTP 
status code");
+    GNUNET_free (ih);
+    return;
+  }
+}
+
+
+/**
+ * Logic to asynchronously return the response for how to begin the OAuth2.0
+ * checking process to the client.  May first request a dynamic URL via
+ * ``/setup`` if configured to use a client-authenticated setup process.
+ *
+ * @param cls a `struct TALER_KYCLOGIC_InitiateHandle *`
+ */
+static void
+initiate_task (void *cls)
+{
+  struct TALER_KYCLOGIC_InitiateHandle *ih = cls;
+  const struct TALER_KYCLOGIC_ProviderDetails *pd = ih->pd;
+  struct PluginState *ps = pd->ps;
+  char *hdr;
+  struct curl_slist *slist;
+  CURL *eh;
+
+  ih->task = NULL;
+  if (NULL == pd->setup_url)
+  {
+    initiate_with_url (ih,
+                       pd->authorize_url);
+    return;
+  }
+  eh = curl_easy_init ();
+  if (NULL == eh)
+  {
+    GNUNET_break (0);
+    ih->cb (ih->cb_cls,
+            TALER_EC_GENERIC_ALLOCATION_FAILURE,
+            NULL,
+            NULL,
+            NULL,
+            "curl_easy_init() failed");
+    GNUNET_free (ih);
+    return;
+  }
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_URL,
+                                   pd->setup_url));
+  GNUNET_asprintf (&hdr,
+                   "%s: Bearer %s",
+                   MHD_HTTP_HEADER_AUTHORIZATION,
+                   pd->client_secret);
+  slist = curl_slist_append (NULL,
+                             hdr);
+  ih->job = GNUNET_CURL_job_add2 (ps->curl_ctx,
+                                  eh,
+                                  slist,
+                                  &handle_curl_setup_finished,
+                                  ih);
+  curl_slist_free_all (slist);
+  GNUNET_free (hdr);
+}
+
+
 /**
  * Initiate KYC check.
  *
@@ -584,6 +756,11 @@ oauth2_initiate_cancel (struct 
TALER_KYCLOGIC_InitiateHandle *ih)
     GNUNET_SCHEDULER_cancel (ih->task);
     ih->task = NULL;
   }
+  if (NULL != ih->job)
+  {
+    GNUNET_CURL_job_cancel (ih->job);
+    ih->job = NULL;
+  }
   GNUNET_free (ih);
 }
 
@@ -1002,7 +1179,7 @@ handle_curl_login_finished (void *cls,
       eh = curl_easy_init ();
       if (NULL == eh)
       {
-        GNUNET_break_op (0);
+        GNUNET_break (0);
         ph->response
           = TALER_MHD_make_error (
               TALER_EC_GENERIC_ALLOCATION_FAILURE,
@@ -1129,7 +1306,7 @@ oauth2_proof (void *cls,
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (ph->eh,
                                    CURLOPT_URL,
-                                   pd->auth_url));
+                                   pd->token_url));
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (ph->eh,
                                    CURLOPT_POST,
diff --git a/src/testing/test_kyc_api.conf b/src/testing/test_kyc_api.conf
index 9c0b4363..1e575320 100644
--- a/src/testing/test_kyc_api.conf
+++ b/src/testing/test_kyc_api.conf
@@ -53,8 +53,8 @@ LOGIC = oauth2
 USER_TYPE = INDIVIDUAL
 PROVIDED_CHECKS = DUMMY
 KYC_OAUTH2_VALIDITY = forever
-KYC_OAUTH2_AUTH_URL = http://localhost:6666/oauth/v2/token
-KYC_OAUTH2_LOGIN_URL = http://localhost:6666/oauth/v2/login
+KYC_OAUTH2_TOKEN_URL = http://localhost:6666/oauth/v2/token
+KYC_OAUTH2_AUTHORIZE_URL = http://localhost:6666/oauth/v2/login
 KYC_OAUTH2_INFO_URL = http://localhost:6666/api/user/me
 KYC_OAUTH2_CLIENT_ID = taler-exchange
 KYC_OAUTH2_CLIENT_SECRET = exchange-secret

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]