[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnunet] branch master updated: REST: refactor OIDC plugin,
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnunet] branch master updated: REST: refactor OIDC plugin, towards cancel logic |
Date: |
Wed, 28 Nov 2018 08:46:38 +0100 |
This is an automated email from the git hooks/post-receive script.
martin-schanzenbach pushed a commit to branch master
in repository gnunet.
The following commit(s) were added to refs/heads/master by this push:
new 6af0c6d7c REST: refactor OIDC plugin, towards cancel logic
6af0c6d7c is described below
commit 6af0c6d7c6b7f915b832df2bbb907e688deaa452
Author: Schanzenbach, Martin <address@hidden>
AuthorDate: Wed Nov 28 08:46:36 2018 +0100
REST: refactor OIDC plugin, towards cancel logic
---
src/rest-plugins/plugin_rest_openid_connect.c | 385 ++++++++++++++------------
1 file changed, 215 insertions(+), 170 deletions(-)
diff --git a/src/rest-plugins/plugin_rest_openid_connect.c
b/src/rest-plugins/plugin_rest_openid_connect.c
index 3a0106c10..9325d5825 100644
--- a/src/rest-plugins/plugin_rest_openid_connect.c
+++ b/src/rest-plugins/plugin_rest_openid_connect.c
@@ -136,6 +136,11 @@
#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
/**
+ * OIDC cookie header if user cancelled
+ */
+#define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
+
+/**
* OIDC expected response_type while authorizing
*/
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
@@ -243,6 +248,11 @@ struct OIDC_Variables
char *login_identity;
/**
+ * User cancelled authorization/login
+ */
+ int user_cancelled;
+
+ /**
* The response JSON
*/
json_t *response;
@@ -705,6 +715,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
return;
}
+
/**
* Interprets cookie header and pass its identity keystring to handle
*/
@@ -719,49 +730,70 @@ cookie_identity_interpretation (struct RequestHandle
*handle)
//gets identity of login try with cookie
GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY),
&cache_key);
- if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains
(handle->rest_handle->header_param_map,
+ if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains
(handle->rest_handle->header_param_map,
&cache_key) )
{
- //splits cookies and find 'Identity' cookie
- cookies = GNUNET_CONTAINER_multihashmap_get (
handle->rest_handle->header_param_map, &cache_key);
- handle->oidc->login_identity = strtok(cookies, delimiter);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No cookie found\n");
+ return;
+ }
+ //splits cookies and find 'Identity' cookie
+ cookies = GNUNET_CONTAINER_multihashmap_get (
handle->rest_handle->header_param_map, &cache_key);
+ handle->oidc->login_identity = strtok (cookies, delimiter);
+ handle->oidc->user_cancelled = GNUNET_NO;
- while ( NULL != handle->oidc->login_identity )
- {
- if ( NULL != strstr (handle->oidc->login_identity,
OIDC_COOKIE_HEADER_INFORMATION_KEY) )
- {
- break;
- }
- handle->oidc->login_identity = strtok (NULL, delimiter);
- }
- GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen
(handle->oidc->login_identity),
- &cache_key);
- if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains
(OIDC_identity_login_time, &cache_key) )
- {
- relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
- &cache_key);
- current_time = GNUNET_TIME_absolute_get ();
- // 30 min after old login -> redirect to login
- if ( current_time.abs_value_us <= relog_time->abs_value_us )
- {
- handle->oidc->login_identity = strtok(handle->oidc->login_identity,
OIDC_COOKIE_HEADER_INFORMATION_KEY);
- handle->oidc->login_identity =
GNUNET_strdup(handle->oidc->login_identity);
- } else {
- handle->oidc->login_identity = NULL;
- }
- }
- else
+ if (NULL == handle->oidc->login_identity)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse cookie: %s\n",
+ cookies);
+ return;
+ }
+
+ while ( NULL != handle->oidc->login_identity )
+ {
+ if ( 0 == strcmp (handle->oidc->login_identity,
+ OIDC_COOKIE_HEADER_ACCESS_DENIED))
{
+ handle->oidc->user_cancelled = GNUNET_YES;
handle->oidc->login_identity = NULL;
+ return;
}
+ if ( NULL != strstr (handle->oidc->login_identity,
OIDC_COOKIE_HEADER_INFORMATION_KEY) )
+ break;
+ handle->oidc->login_identity = strtok (NULL, delimiter);
}
+ GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen
(handle->oidc->login_identity),
+ &cache_key);
+ if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains
(OIDC_identity_login_time, &cache_key) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Found cookie `%s', but no corresponding expiration entry
present...\n",
+ handle->oidc->login_identity);
+ handle->oidc->login_identity = NULL;
+ return;
+ }
+ relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
+ &cache_key);
+ current_time = GNUNET_TIME_absolute_get ();
+ // 30 min after old login -> redirect to login
+ if ( current_time.abs_value_us > relog_time->abs_value_us )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Found cookie `%s', but it is expired.\n",
+ handle->oidc->login_identity);
+ handle->oidc->login_identity = NULL;
+ return;
+ }
+ handle->oidc->login_identity = strtok(handle->oidc->login_identity,
OIDC_COOKIE_HEADER_INFORMATION_KEY);
+ handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity);
}
/**
* Redirects to login page stored in configuration file
*/
static void
-login_redirection(void *cls)
+login_redirect (void *cls)
{
char *login_base_url;
char *new_redirect;
@@ -815,12 +847,14 @@ oidc_iteration_error (void *cls)
GNUNET_SCHEDULER_add_now (&do_error, handle);
}
+
+/**
+ * Issues ticket and redirects to relying party with the authorization code as
+ * parameter. Otherwise redirects with error
+ */
static void
-get_client_name_result (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
- const char *label,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
+oidc_ticket_issue_cb (void* cls,
+ const struct GNUNET_RECLAIM_Ticket *ticket)
{
struct RequestHandle *handle = cls;
struct MHD_Response *resp;
@@ -829,6 +863,15 @@ get_client_name_result (void *cls,
char *code_json_string;
char *code_base64_final_string;
+ handle->idp_op = NULL;
+ handle->ticket = *ticket;
+ if (NULL == ticket)
+ {
+ handle->emsg = GNUNET_strdup("server_error");
+ handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
+ GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+ return;
+ }
ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
sizeof (struct
GNUNET_RECLAIM_Ticket));
//TODO change if more attributes are needed (see max_age)
@@ -850,106 +893,6 @@ get_client_name_result (void *cls,
GNUNET_free (ticket_str);
GNUNET_free (code_json_string);
GNUNET_free (code_base64_final_string);
- return;
-
-}
-
-
-static void
-get_client_name_error (void *cls)
-{
- struct RequestHandle *handle = cls;
-
- handle->emsg = GNUNET_strdup("server_error");
- handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found
for client.");
- GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-
-static void
-lookup_redirect_uri_result (void *cls,
- uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
-{
- struct RequestHandle *handle = cls;
- char *tmp;
- char *tmp_key_str;
- char *pos;
- struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
-
- handle->gns_op = NULL;
- if (0 == rd_count)
- {
- handle->emsg = GNUNET_strdup("server_error");
- handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri
not found.");
- GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
- return;
- }
- for (int i = 0; i < rd_count; i++)
- {
- if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
- continue;
- if (0 != strcmp (rd[i].data,
- handle->oidc->redirect_uri))
- continue;
- tmp = GNUNET_strdup (rd[i].data);
- pos = strrchr (tmp,
- (unsigned char) '.');
- *pos = '\0';
- handle->redirect_prefix = GNUNET_strdup (tmp);
- tmp_key_str = pos + 1;
- pos = strchr (tmp_key_str,
- (unsigned char) '/');
- *pos = '\0';
- handle->redirect_suffix = GNUNET_strdup (pos + 1);
-
- GNUNET_STRINGS_string_to_data (tmp_key_str,
- strlen (tmp_key_str),
- &redirect_zone,
- sizeof (redirect_zone));
-
- GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle,
- &handle->priv_key,
- &redirect_zone,
- &get_client_name_error,
- handle,
- &get_client_name_result,
- handle);
- GNUNET_free (tmp);
- return;
- }
- handle->emsg = GNUNET_strdup("server_error");
- handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri
not found.");
- GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-/**
- * Issues ticket and redirects to relying party with the authorization code as
- * parameter. Otherwise redirects with error
- */
-static void
-oidc_ticket_issue_cb (void* cls,
- const struct GNUNET_RECLAIM_Ticket *ticket)
-{
- struct RequestHandle *handle = cls;
-
- handle->idp_op = NULL;
- handle->ticket = *ticket;
- if (NULL == ticket)
- {
- handle->emsg = GNUNET_strdup("server_error");
- handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
- GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
- return;
- }
- handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle,
- "+",
- &handle->oidc->client_pkey,
-
GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
- GNUNET_GNS_LO_DEFAULT,
- &lookup_redirect_uri_result,
- handle);
-
}
static void
@@ -1025,7 +968,7 @@ oidc_attr_collect (void *cls,
* Checks time and cookie and redirects accordingly
*/
static void
-login_check (void *cls)
+code_redirect (void *cls)
{
struct RequestHandle *handle = cls;
struct GNUNET_TIME_Absolute current_time, *relog_time;
@@ -1067,27 +1010,126 @@ login_check (void *cls)
== memcmp (&ego_pkey, &pubkey,
sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
{
- handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (
-
handle->ego_entry->ego);
+ handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key
(handle->ego_entry->ego);
handle->idp = GNUNET_RECLAIM_connect (cfg);
- handle->attr_list = GNUNET_new(
- struct
GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
- handle->attr_it = GNUNET_RECLAIM_get_attributes_start (
- handle->idp,
&handle->priv_key, &oidc_iteration_error, handle,
-
&oidc_attr_collect, handle, &oidc_collect_finished_cb, handle);
+ handle->attr_list = GNUNET_new(struct
GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+ handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+
&handle->priv_key,
+
&oidc_iteration_error,
+ handle,
+
&oidc_attr_collect,
+ handle,
+
&oidc_collect_finished_cb,
+ handle);
return;
}
}
- //handle->emsg = GNUNET_strdup("invalid_cookie");
- //handle->edesc = GNUNET_strdup(
- // "The cookie of the login identity is not
valid");
- //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
- GNUNET_SCHEDULER_add_now (&login_redirection,handle);
+ GNUNET_SCHEDULER_add_now (&login_redirect, handle);
return;
}
}
}
+
+static void
+build_redirect (void *cls)
+{
+ struct RequestHandle *handle = cls;
+ struct MHD_Response *resp;
+ char* redirect_uri;
+
+ if (GNUNET_YES == handle->oidc->user_cancelled)
+ {
+ GNUNET_asprintf (&redirect_uri,
"%s.%s/%s?error=%s&error_description=%s&state=%s",
+ handle->redirect_prefix,
+ handle->tld,
+ handle->redirect_suffix,
+ "access_denied",
+ "User denied access",
+ handle->oidc->state);
+ resp = GNUNET_REST_create_response ("");
+ MHD_add_response_header (resp, "Location", redirect_uri);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+ GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+ GNUNET_free (redirect_uri);
+ return;
+ }
+ GNUNET_SCHEDULER_add_now (&code_redirect, handle);
+}
+
+
+static void
+lookup_redirect_uri_result (void *cls,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct RequestHandle *handle = cls;
+ char *tmp;
+ char *tmp_key_str;
+ char *pos;
+ struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
+
+ handle->gns_op = NULL;
+ if (0 == rd_count)
+ {
+ handle->emsg = GNUNET_strdup("server_error");
+ handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri
not found.");
+ GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+ return;
+ }
+ for (int i = 0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
+ continue;
+ if (0 != strcmp (rd[i].data,
+ handle->oidc->redirect_uri))
+ continue;
+ tmp = GNUNET_strdup (rd[i].data);
+ pos = strrchr (tmp,
+ (unsigned char) '.');
+ *pos = '\0';
+ handle->redirect_prefix = GNUNET_strdup (tmp);
+ tmp_key_str = pos + 1;
+ pos = strchr (tmp_key_str,
+ (unsigned char) '/');
+ *pos = '\0';
+ handle->redirect_suffix = GNUNET_strdup (pos + 1);
+
+ GNUNET_STRINGS_string_to_data (tmp_key_str,
+ strlen (tmp_key_str),
+ &redirect_zone,
+ sizeof (redirect_zone));
+ GNUNET_SCHEDULER_add_now (&build_redirect, handle);
+ GNUNET_free (tmp);
+ return;
+ }
+ handle->emsg = GNUNET_strdup("server_error");
+ handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri
not found.");
+ GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+}
+
+
+
+/**
+ * Initiate redirect back to client.
+ */
+static void
+client_redirect (void *cls)
+{
+ struct RequestHandle *handle = cls;
+
+ /* Lookup client redirect uri to verify request */
+ handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle,
+ "+",
+ &handle->oidc->client_pkey,
+
GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
+ GNUNET_GNS_LO_DEFAULT,
+ &lookup_redirect_uri_result,
+ handle);
+
+}
+
+
/**
* Iteration over all results finished, build final
* response.
@@ -1210,13 +1252,11 @@ build_authz_response (void *cls)
GNUNET_free(expected_scope);
- if( NULL != handle->oidc->login_identity )
- {
- GNUNET_SCHEDULER_add_now(&login_check,handle);
- return;
- }
-
- GNUNET_SCHEDULER_add_now(&login_redirection,handle);
+ if ( (NULL == handle->oidc->login_identity) &&
+ (GNUNET_NO == handle->oidc->user_cancelled))
+ GNUNET_SCHEDULER_add_now (&login_redirect, handle);
+ else
+ GNUNET_SCHEDULER_add_now (&client_redirect, handle);
}
/**
@@ -1264,7 +1304,7 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle
*con_handle,
const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
- cookie_identity_interpretation(handle);
+ cookie_identity_interpretation (handle);
//RECOMMENDED value: state - REQUIRED for answers
GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key);
@@ -1366,13 +1406,24 @@ login_cont (struct GNUNET_REST_RequestHandle
*con_handle,
GNUNET_memcpy (term_data, handle->rest_handle->data,
handle->rest_handle->data_size);
root = json_loads (term_data, JSON_DECODE_ANY, &error);
identity = json_object_get (root, "identity");
- if ( json_is_string(identity) )
+ if ( !json_is_string(identity) )
{
- GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
- MHD_add_response_header (resp, "Set-Cookie", cookie);
- MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
- GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error parsing json string from %s\n",
+ term_data);
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+ json_decref (root);
+ GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+ return;
+ }
+ GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
+ MHD_add_response_header (resp, "Set-Cookie", cookie);
+ MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
+ GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
+ if (0 != strcmp (json_string_value (identity),
+ "Denied"))
+ {
current_time = GNUNET_new(struct GNUNET_TIME_Absolute);
*current_time = GNUNET_TIME_relative_to_absolute (
GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
@@ -1385,20 +1436,14 @@ login_cont (struct GNUNET_REST_RequestHandle
*con_handle,
GNUNET_CONTAINER_multihashmap_put (
OIDC_identity_login_time, &cache_key,
current_time,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
- handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- GNUNET_free(cookie);
- }
- else
- {
- handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
}
+ handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+ GNUNET_free(cookie);
json_decref (root);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
- return;
}
-static int
+static int
check_authorization (struct RequestHandle *handle,
struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
{
--
To stop receiving notification emails like this one, please contact
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [gnunet] branch master updated: REST: refactor OIDC plugin, towards cancel logic,
gnunet <=