obsolete due to alpine policy
[oweals/gnunet.git] / src / reclaim / plugin_rest_openid_connect.c
index 11d6d743d4e4de09efe547f45c71cf1e722b0bff..a4a368ab58154035e5811d6da87966e127d47d6a 100644 (file)
@@ -15,8 +15,8 @@
    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-     SPDX-License-Identifier: AGPL3.0-or-later
  */
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
 /**
  * @author Martin Schanzenbach
  * @author Philippe Buschmann
  */
 #define OIDC_NONCE_KEY "nonce"
 
+/**
+ * OIDC PKCE code challenge
+ */
+#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
+
+/**
+ * OIDC PKCE code verifier
+ */
+#define OIDC_CODE_VERIFIER_KEY "code_verifier"
+
 /**
  * OIDC cookie expiration (in seconds)
  */
 /**
  * OIDC ignored parameter array
  */
-static char *OIDC_ignored_parameter_array[] = {"display",
-                                               "prompt",
-                                               "ui_locales",
-                                               "response_mode",
-                                               "id_token_hint",
-                                               "login_hint",
-                                               "acr_values"};
+static char *OIDC_ignored_parameter_array[] = { "display",
+                                                "prompt",
+                                                "ui_locales",
+                                                "response_mode",
+                                                "id_token_hint",
+                                                "login_hint",
+                                                "acr_values" };
 
 /**
  * OIDC Hash map that keeps track of issued cookies
@@ -295,6 +305,16 @@ struct OIDC_Variables
    */
   int user_cancelled;
 
+  /**
+   * The PKCE code_challenge
+   */
+  char *code_challenge;
+
+  /**
+   * The PKCE code_verifier
+   */
+  char *code_verifier;
+
   /**
    * The response JSON
    */
@@ -497,6 +517,7 @@ cleanup_handle (struct RequestHandle *handle)
   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
   struct EgoEntry *ego_entry;
   struct EgoEntry *ego_tmp;
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
@@ -552,7 +573,6 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_free (ego_tmp->keystring);
     GNUNET_free (ego_tmp);
   }
-  GNUNET_free_non_null (handle->attr_it);
   GNUNET_free (handle);
 }
 
@@ -632,6 +652,7 @@ do_redirect_error (void *cls)
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
   char *redirect;
+
   GNUNET_asprintf (&redirect,
                    "%s?error=%s&error_description=%s%s%s",
                    handle->oidc->redirect_uri,
@@ -724,7 +745,7 @@ cookie_identity_interpretation (struct RequestHandle *handle)
                       strlen (OIDC_COOKIE_HEADER_KEY),
                       &cache_key);
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
-                                                             ->header_param_map,
+                                                           ->header_param_map,
                                                            &cache_key))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
@@ -793,6 +814,7 @@ cookie_identity_interpretation (struct RequestHandle *handle)
   value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
   GNUNET_assert (NULL != value);
   handle->oidc->login_identity = GNUNET_strdup (value);
+  GNUNET_free (cookies);
 }
 
 /**
@@ -812,7 +834,7 @@ login_redirect (void *cls)
                                                           &login_base_url))
   {
     GNUNET_asprintf (&new_redirect,
-                     "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
+                     "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
                      login_base_url,
                      OIDC_RESPONSE_TYPE_KEY,
                      handle->oidc->response_type,
@@ -824,6 +846,9 @@ login_redirect (void *cls)
                      handle->oidc->scope,
                      OIDC_STATE_KEY,
                      (NULL != handle->oidc->state) ? handle->oidc->state : "",
+                     OIDC_CODE_CHALLENGE_KEY,
+                     (NULL != handle->oidc->code_challenge) ?
+                     handle->oidc->code_challenge : "",
                      OIDC_NONCE_KEY,
                      (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
     resp = GNUNET_REST_create_response ("");
@@ -850,6 +875,7 @@ static void
 oidc_iteration_error (void *cls)
 {
   struct RequestHandle *handle = cls;
+
   handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
   handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
   GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -870,7 +896,6 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   char *code_string;
 
   handle->idp_op = NULL;
-  handle->ticket = *ticket;
   if (NULL == ticket)
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
@@ -878,18 +903,19 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
     GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
     return;
   }
+  handle->ticket = *ticket;
   ticket_str =
     GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
-                                         sizeof (struct GNUNET_RECLAIM_Ticket));
+                                         sizeof(struct GNUNET_RECLAIM_Ticket));
   // TODO change if more attributes are needed (see max_age)
   code_string = OIDC_build_authz_code (&handle->priv_key,
                                        &handle->ticket,
                                        handle->attr_list,
-                                       handle->oidc->nonce);
+                                       handle->oidc->nonce,
+                                       handle->oidc->code_challenge);
   if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
       (NULL != handle->tld))
   {
-
     GNUNET_asprintf (&redirect_uri,
                      "%s.%s/%s?%s=%s&state=%s",
                      handle->redirect_prefix,
@@ -921,6 +947,7 @@ static void
 oidc_collect_finished_cb (void *cls)
 {
   struct RequestHandle *handle = cls;
+
   handle->attr_it = NULL;
   handle->ticket_it = NULL;
   if (NULL == handle->attr_list->list_head)
@@ -980,6 +1007,8 @@ oidc_attr_collect (void *cls,
                                                   attr->type,
                                                   attr->data,
                                                   attr->data_size);
+  le->claim->id = attr->id;
+  le->claim->version = attr->version;
   GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
                                handle->attr_list->list_tail,
                                le);
@@ -1018,10 +1047,10 @@ code_redirect (void *cls)
     {
       if (GNUNET_OK !=
           GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc
-                                                        ->login_identity,
+                                                      ->login_identity,
                                                       strlen (
                                                         handle->oidc
-                                                          ->login_identity),
+                                                        ->login_identity),
                                                       &pubkey))
       {
         handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE);
@@ -1132,25 +1161,40 @@ lookup_redirect_uri_result (void *cls,
     if (NULL == strstr (tmp, handle->oidc->client_id))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Redirect uri %s does not contain client_id %s",
+                  "Redirect uri %s does not contain client_id %s\n",
                   tmp,
                   handle->oidc->client_id);
     }
     else
     {
-
       pos = strrchr (tmp, (unsigned char) '.');
+      if (NULL == pos)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Redirect uri %s contains client_id but is malformed\n",
+                    tmp);
+        GNUNET_free (tmp);
+        continue;
+      }
       *pos = '\0';
       handle->redirect_prefix = GNUNET_strdup (tmp);
       tmp_key_str = pos + 1;
       pos = strchr (tmp_key_str, (unsigned char) '/');
+      if (NULL == pos)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Redirect uri %s contains client_id but is malformed\n",
+                    tmp);
+        GNUNET_free (tmp);
+        continue;
+      }
       *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));
+                                     sizeof(redirect_zone));
     }
     GNUNET_SCHEDULER_add_now (&build_redirect, handle);
     GNUNET_free (tmp);
@@ -1187,9 +1231,10 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
 {
   struct GNUNET_HashCode hc;
   char *value;
+
   GNUNET_CRYPTO_hash (key, strlen (key), &hc);
   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
-                                                              ->url_param_map,
+                                                            ->url_param_map,
                                                             &hc))
     return NULL;
   value =
@@ -1254,7 +1299,7 @@ build_authz_response (void *cls)
 
   // TODO check other values if needed
   number_of_ignored_parameter =
-    sizeof (OIDC_ignored_parameter_array) / sizeof (char *);
+    sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
   for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
   {
     GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
@@ -1262,7 +1307,7 @@ build_authz_response (void *cls)
                         &cache_key);
     if (GNUNET_YES ==
         GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
-                                                  ->url_param_map,
+                                                ->url_param_map,
                                                 &cache_key))
     {
       handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_ACCESS_DENIED);
@@ -1365,6 +1410,15 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
+  // OPTIONAL value: code_challenge
+  handle->oidc->code_challenge = get_url_parameter_copy (handle,
+                                                         OIDC_CODE_CHALLENGE_KEY);
+  if (NULL == handle->oidc->code_challenge)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "OAuth authorization request does not contain PKCE parameters!\n");
+  }
+
   if (GNUNET_OK !=
       GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
                                                   strlen (
@@ -1379,18 +1433,6 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
-  if (NULL == handle->ego_head)
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
-    handle->edesc = GNUNET_strdup ("Egos are missing");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->ego_entry = handle->ego_head;
-  handle->priv_key =
-    *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
   // If we know this identity, translated the corresponding TLD
   // TODO: We might want to have a reverse lookup functionality for TLDs?
   for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
@@ -1433,6 +1475,7 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
   json_error_t error;
   json_t *identity;
   char term_data[handle->rest_handle->data_size + 1];
+
   term_data[handle->rest_handle->data_size] = '\0';
   GNUNET_memcpy (term_data,
                  handle->rest_handle->data,
@@ -1495,7 +1538,7 @@ check_authorization (struct RequestHandle *handle,
                       strlen (OIDC_AUTHORIZATION_HEADER_KEY),
                       &cache_key);
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
-                                                             ->header_param_map,
+                                                           ->header_param_map,
                                                            &cache_key))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
@@ -1509,7 +1552,7 @@ check_authorization (struct RequestHandle *handle,
 
   // split header in "Basic" and [content]
   credentials = strtok (authorization, " ");
-  if (0 != strcmp ("Basic", credentials))
+  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
@@ -1575,8 +1618,7 @@ check_authorization (struct RequestHandle *handle,
   }
 
   // check client_id
-  for (handle->ego_entry = handle->ego_head;
-       NULL != handle->ego_entry;
+  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
        handle->ego_entry = handle->ego_entry->next)
   {
     if (0 == strcmp (handle->ego_entry->keystring, client_id))
@@ -1592,15 +1634,15 @@ check_authorization (struct RequestHandle *handle,
   GNUNET_STRINGS_string_to_data (client_id,
                                  strlen (client_id),
                                  cid,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+                                 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
 
   GNUNET_free (basic_authorization);
   return GNUNET_OK;
 }
 
-static int
-ego_exists (struct RequestHandle *handle,
-            struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
+const struct EgoEntry *
+find_ego (struct RequestHandle *handle,
+          struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
 {
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
@@ -1610,11 +1652,9 @@ ego_exists (struct RequestHandle *handle,
   {
     GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
     if (0 == GNUNET_memcmp (&pub_key, test_key))
-      break;
+      return ego_entry;
   }
-  if (NULL == ego_entry)
-    return GNUNET_NO;
-  return GNUNET_YES;
+  return NULL;
 }
 
 static void
@@ -1628,11 +1668,12 @@ persist_access_token (const struct RequestHandle *handle,
   GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc);
   ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
   *ticketbuf = *ticket;
-  GNUNET_CONTAINER_multihashmap_put (
-    OIDC_access_token_map,
-    &hc,
-    ticketbuf,
-    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  GNUNET_assert (GNUNET_SYSERR !=
+                 GNUNET_CONTAINER_multihashmap_put (
+                   OIDC_access_token_map,
+                   &hc,
+                   ticketbuf,
+                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
 
 /**
@@ -1648,10 +1689,12 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
                 void *cls)
 {
   struct RequestHandle *handle = cls;
+  const struct EgoEntry *ego_entry;
   struct GNUNET_TIME_Relative expiration_time;
   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl;
   struct GNUNET_RECLAIM_Ticket ticket;
   struct GNUNET_CRYPTO_EcdsaPublicKey cid;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
   struct GNUNET_HashCode cache_key;
   struct MHD_Response *resp;
   char *grant_type;
@@ -1661,6 +1704,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   char *access_token;
   char *jwt_secret;
   char *nonce;
+  char *code_verifier;
 
   /*
    * Check Authorization
@@ -1697,10 +1741,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE);
     handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_free (grant_type);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-
+  GNUNET_free (grant_type);
   // REQUIRED code
   code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
   if (NULL == code)
@@ -1711,16 +1756,39 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
+  ego_entry = find_ego (handle, &cid);
+  if (NULL == ego_entry)
+  {
+    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
+    handle->edesc = GNUNET_strdup ("Unknown client");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_free (code);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  // REQUIRED code verifier
+  code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
+  if (NULL == code_verifier)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "OAuth authorization request does not contain PKCE parameters!\n");
+
+  }
 
   // decode code
-  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, &ticket, &cl, &nonce))
+  if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket,
+                                          &cl, &nonce))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
     handle->edesc = GNUNET_strdup ("invalid code");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_free (code);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
+  GNUNET_free (code);
 
   // create jwt
   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1737,13 +1805,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
 
 
   // TODO OPTIONAL acr,amr,azp
-  if (GNUNET_NO == ego_exists (handle, &ticket.audience))
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
-    handle->edesc = GNUNET_strdup ("invalid code...");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
                                                           "reclaim-rest-plugin",
                                                           "jwt_secret",
@@ -1825,15 +1886,14 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   char *authorization_type;
   char *authorization_access_token;
   struct GNUNET_RECLAIM_Ticket *ticket;
+  const struct EgoEntry *ego_entry;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
 
   GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
                       strlen (OIDC_AUTHORIZATION_HEADER_KEY),
                       &cache_key);
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
-                                                             ->header_param_map,
+                                                           ->header_param_map,
                                                            &cache_key))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
@@ -1849,7 +1909,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   // split header in "Bearer" and access_token
   authorization = GNUNET_strdup (authorization);
   authorization_type = strtok (authorization, delimiter);
-  if (0 != strcmp ("Bearer", authorization_type))
+  if ((NULL == authorization_type) ||
+      (0 != strcmp ("Bearer", authorization_type)))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
     handle->edesc = GNUNET_strdup ("No Access Token");
@@ -1886,15 +1947,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   ticket =
     GNUNET_CONTAINER_multihashmap_get (OIDC_access_token_map, &cache_key);
   GNUNET_assert (NULL != ticket);
-
-  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
-       handle->ego_entry = handle->ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &pk);
-    if (0 == GNUNET_memcmp (&pk, &ticket->audience))
-      break; // Found
-  }
-  if (NULL == handle->ego_entry)
+  ego_entry = find_ego (handle, &ticket->audience);
+  if (NULL == ego_entry)
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
     handle->edesc = GNUNET_strdup ("The access token expired");
@@ -1908,9 +1962,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   handle->oidc->response = json_object ();
   json_object_set_new (handle->oidc->response,
                        "sub",
-                       json_string (handle->ego_entry->keystring));
-  privkey = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
-
+                       json_string (ego_entry->keystring));
+  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
   handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
                                                   privkey,
                                                   ticket,
@@ -1930,16 +1983,16 @@ init_cont (struct RequestHandle *handle)
 {
   struct GNUNET_REST_RequestHandlerError err;
   static const struct GNUNET_REST_RequestHandler handlers[] =
-    {{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
-     {MHD_HTTP_METHOD_POST,
+  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
+    MHD_HTTP_METHOD_POST,
       GNUNET_REST_API_NS_AUTHORIZE,
-      &authorize_endpoint}, // url-encoded
-     {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
-     {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint},
-     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
-     {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
-     {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont},
-     GNUNET_REST_HANDLER_END};
+      &authorize_endpoint },   // url-encoded
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
+    GNUNET_REST_HANDLER_END };
 
   if (GNUNET_NO ==
       GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
@@ -1998,7 +2051,9 @@ list_ego (void *cls,
     init_cont (handle);
     return;
   }
+  GNUNET_assert (NULL != ego);
   if (ID_REST_STATE_INIT == handle->state)
+
   {
     ego_entry = GNUNET_new (struct EgoEntry);
     GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
@@ -2059,6 +2114,7 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                                void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+
   handle->oidc = GNUNET_new (struct OIDC_Variables);
   if (NULL == OIDC_cookie_jar_map)
     OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
@@ -2099,7 +2155,7 @@ libgnunet_plugin_rest_openid_connect_init (void *cls)
   cfg = cls;
   if (NULL != plugin.cfg)
     return NULL; /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
+  memset (&plugin, 0, sizeof(struct Plugin));
   plugin.cfg = cfg;
   api = GNUNET_new (struct GNUNET_REST_Plugin);
   api->cls = &plugin;
@@ -2130,6 +2186,7 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
+
   plugin->cfg = NULL;
 
   struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
@@ -2139,6 +2196,7 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
   while (GNUNET_YES ==
          GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
     GNUNET_free_non_null (value);
+  GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
   GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
 
   hashmap_it =