complete oauth logic (in theory)
This commit is contained in:
parent
0325a79631
commit
e5ead88057
@ -1194,6 +1194,34 @@ parse_kyc_oauth_cfg (void)
|
||||
}
|
||||
TEH_kyc_config.details.oauth2.url = s;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_INFO_URL",
|
||||
&s))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_INFO_URL");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (! TALER_url_valid_charset (s)) ||
|
||||
( (0 != strncasecmp (s,
|
||||
"http://",
|
||||
strlen ("http://"))) &&
|
||||
(0 != strncasecmp (s,
|
||||
"https://",
|
||||
strlen ("https://"))) ) )
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_INFO_URL",
|
||||
"not a valid URL");
|
||||
GNUNET_free (s);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TEH_kyc_config.details.oauth2.info_url = s;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||
"exchange-kyc-oauth2",
|
||||
|
@ -91,10 +91,15 @@ struct TEH_KycOptions
|
||||
{
|
||||
|
||||
/**
|
||||
* URL of tue OAuth2.0 endpoint for KYC checks.
|
||||
* URL of the OAuth2.0 endpoint for KYC checks.
|
||||
*/
|
||||
char *url;
|
||||
|
||||
/**
|
||||
* URL of the user info access endpoint.
|
||||
*/
|
||||
char *info_url;
|
||||
|
||||
/**
|
||||
* Our client ID for OAuth2.0.
|
||||
*/
|
||||
|
@ -72,6 +72,11 @@ struct KycProofContext
|
||||
*/
|
||||
char *post_body;
|
||||
|
||||
/**
|
||||
* User ID extracted from the OAuth 2.0 service, or NULL.
|
||||
*/
|
||||
char *id;
|
||||
|
||||
/**
|
||||
* Payment target this is about.
|
||||
*/
|
||||
@ -165,13 +170,186 @@ persist_kyc_ok (void *cls,
|
||||
struct KycProofContext *kpc = cls;
|
||||
|
||||
return TEH_plugin->set_kyc_ok (TEH_plugin->cls,
|
||||
kpc->payment_target_uuid);
|
||||
kpc->payment_target_uuid,
|
||||
kpc->id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The request for @a kpc failed. We may have gotten a useful error
|
||||
* message in @a j. Generate a failure response.
|
||||
*
|
||||
* @param[in,out] kpc request that failed
|
||||
* @param j reply from the server (or NULL)
|
||||
*/
|
||||
static void
|
||||
handle_error (struct KycProofContext *kpc,
|
||||
const json_t *j)
|
||||
{
|
||||
const char *msg;
|
||||
const char *desc;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("error",
|
||||
&msg),
|
||||
GNUNET_JSON_spec_string ("error_description",
|
||||
&desc),
|
||||
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)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
|
||||
"Unexpected response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
|
||||
we MAY want to in the future look at the requested content type
|
||||
and possibly respond in JSON if indicated. */
|
||||
{
|
||||
char *reply;
|
||||
|
||||
GNUNET_asprintf (&reply,
|
||||
"<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
|
||||
msg,
|
||||
msg,
|
||||
desc);
|
||||
kpc->response
|
||||
= MHD_create_response_from_buffer (strlen (reply),
|
||||
reply,
|
||||
MHD_RESPMEM_MUST_COPY);
|
||||
GNUNET_assert (NULL != kpc->response);
|
||||
GNUNET_free (reply);
|
||||
}
|
||||
kpc->response_code = MHD_HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The request for @a kpc succeeded (presumably).
|
||||
* Parse the user ID and store it in @a kpc (if possible).
|
||||
*
|
||||
* @param[in,out] kpc request that succeeded
|
||||
* @param j reply from the server
|
||||
*/
|
||||
static void
|
||||
parse_success_reply (struct KycProofContext *kpc,
|
||||
const json_t *j)
|
||||
{
|
||||
const char *state;
|
||||
json_t *data;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("status",
|
||||
&state),
|
||||
GNUNET_JSON_spec_json ("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)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
|
||||
"Unexpected response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
return;
|
||||
}
|
||||
if (0 != strcasecmp (state,
|
||||
"success"))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
handle_error (kpc,
|
||||
j);
|
||||
return;
|
||||
}
|
||||
{
|
||||
const char *id;
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_string ("id",
|
||||
&id),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
res = GNUNET_JSON_parse (data,
|
||||
ispec,
|
||||
&emsg,
|
||||
&line);
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
|
||||
"Unexpected response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
return;
|
||||
}
|
||||
kpc->id = GNUNET_strdup (id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* After we are done with the CURL interaction we
|
||||
* need to update our database state.
|
||||
* need to update our database state with the information
|
||||
* retrieved.
|
||||
*
|
||||
* @param cls our `struct KycProofContext`
|
||||
* @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_fetch_finished (void *cls,
|
||||
long response_code,
|
||||
const void *response)
|
||||
{
|
||||
struct KycProofContext *kpc = cls;
|
||||
const json_t *j = response;
|
||||
|
||||
kpc->job = NULL;
|
||||
switch (response_code)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
parse_success_reply (kpc,
|
||||
j);
|
||||
break;
|
||||
default:
|
||||
handle_error (kpc,
|
||||
j);
|
||||
break;
|
||||
}
|
||||
kpc_resume (kpc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* After we are done with the CURL interaction we
|
||||
* need to fetch the user's account details.
|
||||
*
|
||||
* @param cls our `struct KycProofContext`
|
||||
* @param response_code HTTP response code from server, 0 on hard error
|
||||
@ -205,6 +383,7 @@ handle_curl_login_finished (void *cls,
|
||||
&refresh_token),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
CURL *eh;
|
||||
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
@ -224,8 +403,7 @@ handle_curl_login_finished (void *cls,
|
||||
"Unexpected response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
kpc_resume (kpc);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 != strcasecmp (token_type,
|
||||
@ -238,74 +416,72 @@ handle_curl_login_finished (void *cls,
|
||||
"Unexpected token type in response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
kpc_resume (kpc);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Here we might want to keep something to persist in the DB, and
|
||||
possibly use the access_token to download information we should
|
||||
persist; then continue! */
|
||||
/* We guard against a few characters that could
|
||||
conceivably be abused to mess with the HTTP header */
|
||||
if ( (NULL != strchr (access_token,
|
||||
'\n')) ||
|
||||
(NULL != strchr (access_token,
|
||||
'\r')) ||
|
||||
(NULL != strchr (access_token,
|
||||
' ')) ||
|
||||
(NULL != strchr (access_token,
|
||||
';')) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
|
||||
"Illegal character in access token");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
break;
|
||||
}
|
||||
|
||||
kpc_resume (kpc);
|
||||
eh = curl_easy_init ();
|
||||
if (NULL == eh)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_GENERIC_ALLOCATION_FAILURE,
|
||||
"curl_easy_init");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
break;
|
||||
}
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_URL,
|
||||
TEH_kyc_config.details.oauth2.info_url));
|
||||
{
|
||||
char *hdr;
|
||||
struct curl_slist *slist;
|
||||
|
||||
GNUNET_asprintf (&hdr,
|
||||
"%s: Bearer %s",
|
||||
MHD_HTTP_HEADER_AUTHORIZATION,
|
||||
access_token);
|
||||
slist = curl_slist_append (NULL,
|
||||
hdr);
|
||||
kpc->job = GNUNET_CURL_job_add2 (TEH_curl_ctx,
|
||||
eh,
|
||||
slist,
|
||||
&handle_curl_fetch_finished,
|
||||
kpc);
|
||||
curl_slist_free_all (slist);
|
||||
GNUNET_free (hdr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
const char *msg;
|
||||
const char *desc;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("error",
|
||||
&msg),
|
||||
GNUNET_JSON_spec_string ("error_description",
|
||||
&desc),
|
||||
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)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
kpc->response
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
|
||||
"Unexpected response from KYC gateway");
|
||||
kpc->response_code
|
||||
= MHD_HTTP_BAD_GATEWAY;
|
||||
kpc_resume (kpc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
|
||||
we MAY want to in the future look at the requested content type
|
||||
and possibly respond in JSON if indicated. */
|
||||
{
|
||||
char *reply;
|
||||
|
||||
GNUNET_asprintf (&reply,
|
||||
"<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
|
||||
msg,
|
||||
msg,
|
||||
desc);
|
||||
kpc->response
|
||||
= MHD_create_response_from_buffer (strlen (reply),
|
||||
reply,
|
||||
MHD_RESPMEM_MUST_COPY);
|
||||
GNUNET_assert (NULL != kpc->response);
|
||||
GNUNET_free (reply);
|
||||
}
|
||||
kpc->response_code = MHD_HTTP_FORBIDDEN;
|
||||
kpc_resume (kpc);
|
||||
}
|
||||
handle_error (kpc,
|
||||
j);
|
||||
break;
|
||||
}
|
||||
kpc_resume (kpc);
|
||||
}
|
||||
|
||||
|
||||
@ -331,6 +507,7 @@ clean_kpc (struct TEH_RequestContext *rc)
|
||||
}
|
||||
GNUNET_free (kpc->post_body);
|
||||
GNUNET_free (kpc->token_url);
|
||||
GNUNET_free (kpc->id);
|
||||
GNUNET_free (kpc);
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ CREATE TABLE IF NOT EXISTS wire_targets
|
||||
,h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=64)
|
||||
,payto_uri VARCHAR NOT NULL
|
||||
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
|
||||
,oauth_username VARCHAR
|
||||
,external_id VARCHAR
|
||||
,PRIMARY KEY (h_payto)
|
||||
);
|
||||
COMMENT ON TABLE wire_targets
|
||||
|
@ -383,8 +383,9 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
"set_kyc_ok",
|
||||
"UPDATE wire_targets"
|
||||
" SET kyc_ok=TRUE"
|
||||
",external_id=$2"
|
||||
" WHERE wire_target_serial_id=$1",
|
||||
1),
|
||||
2),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"get_kyc_h_payto",
|
||||
"SELECT"
|
||||
@ -3799,17 +3800,18 @@ postgres_reserves_get (void *cls,
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param payment_target_uuid which account has been checked
|
||||
* @param ... possibly additional data to persist (TODO)
|
||||
* @param id external ID to persist
|
||||
* @return transaction status
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_set_kyc_ok (void *cls,
|
||||
uint64_t payment_target_uuid,
|
||||
...)
|
||||
const char *id)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
|
||||
GNUNET_PQ_query_param_string (id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct TALER_KycCompletedEventP rep = {
|
||||
|
@ -2376,13 +2376,13 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param payment_target_uuid which account has been checked
|
||||
* @param ... possibly additional data to persist (TODO)
|
||||
* @param id ID data to persist
|
||||
* @return transaction status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*set_kyc_ok)(void *cls,
|
||||
uint64_t payment_target_uuid,
|
||||
...);
|
||||
const char *id);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -169,6 +169,28 @@ handler_cb (void *cls,
|
||||
unsigned int hc;
|
||||
json_t *body;
|
||||
|
||||
if (0 == strcasecmp (method,
|
||||
MHD_HTTP_METHOD_GET))
|
||||
{
|
||||
body = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_string (
|
||||
"status",
|
||||
"success"),
|
||||
GNUNET_JSON_pack_object_steal (
|
||||
"data",
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_string ("id",
|
||||
"XXXID12345678"))));
|
||||
return TALER_MHD_reply_json_steal (connection,
|
||||
body,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
if (0 != strcasecmp (method,
|
||||
MHD_HTTP_METHOD_POST))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (NULL == rc)
|
||||
{
|
||||
rc = GNUNET_new (struct RequestCtx);
|
||||
|
Loading…
Reference in New Issue
Block a user