- merge with master
[oweals/gnunet.git] / src / identity-provider / plugin_rest_identity_provider.c
index 3250a9fbd35e27459caf3797f23335213e8226c3..5ea7b28219f97903f1407f9f8ca6ada23114cb75 100644 (file)
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+   Copyright (C) 2012-2015 GNUnet e.V.
 
    GNUnet is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
 #include "gnunet_gnsrecord_lib.h"
 #include "gnunet_namestore_service.h"
 #include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
 #include "microhttpd.h"
 #include <jansson.h>
+#include <inttypes.h>
 #include "gnunet_signatures.h"
 #include "gnunet_identity_provider_service.h"
 
 #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/idp/token"
 
 /**
- * The URL parameter name in which the ticket must be provided
+ * The parameter name in which the ticket must be provided
  */
 #define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET "ticket"
 
+/**
+ * The parameter name in which the expected nonce must be provided
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE "expected_nonce"
+
+/**
+ * The parameter name in which the ticket must be provided
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN "token"
+
 /**
  * The URL parameter name in which the nonce must be provided
  */
  */
 #define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
 
+/**
+ * Attributes passed to issue request
+ */
+#define GNUNET_IDENTITY_TOKEN_V_ATTR_LIST "requested_verified_attrs"
+
+
 /**
  * Token expiration string
  */
@@ -139,12 +158,12 @@ struct EgoEntry
    * DLL
    */
   struct EgoEntry *next;
-  
+
   /**
    * DLL
    */
   struct EgoEntry *prev;
-  
+
   /**
    * Ego Identifier
    */
@@ -154,7 +173,7 @@ struct EgoEntry
    * Public key string
    */
   char *keystring;
-  
+
   /**
    * The Ego
    */
@@ -178,7 +197,7 @@ struct RequestHandle
    * Selected ego
    */
   struct EgoEntry *ego_entry;
-  
+
   /**
    * Ptr to current ego private key
    */
@@ -187,8 +206,8 @@ struct RequestHandle
   /**
    * Handle to the rest connection
    */
-  struct RestConnectionDataHandle *conndata_handle;
-  
+  struct GNUNET_REST_RequestHandle *conndata_handle;
+
   /**
    * The processing state
    */
@@ -237,8 +256,8 @@ struct RequestHandle
   /**
    * ID of a task associated with the resolution process.
    */
-  struct GNUNET_SCHEDULER_Task * timeout_task;    
-  
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
   /**
    * The plugin result processor
    */
@@ -259,10 +278,15 @@ struct RequestHandle
    */
   char *emsg;
 
+  /**
+   * Reponse code
+   */
+  int response_code;
+
   /**
    * Response object
    */
-  struct JsonApiObject *resp_object;
+  struct GNUNET_JSONAPI_Document *resp_object;
 
 };
 
@@ -278,8 +302,8 @@ cleanup_handle (struct RequestHandle *handle)
   struct EgoEntry *ego_tmp;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
-  if (NULL != handle->resp_object) 
-    GNUNET_REST_jsonapi_object_delete (handle->resp_object);
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
   if (NULL != handle->identity_handle)
@@ -310,14 +334,12 @@ cleanup_handle (struct RequestHandle *handle)
 
 
 /**
- * Task run on shutdown.  Cleans up everything.
+ * Task run on error, sends error message.  Cleans up everything.
  *
- * @param cls unused
- * @param tc scheduler context
+ * @param cls the `struct RequestHandle`
  */
 static void
-do_error (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_error (void *cls)
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
@@ -326,24 +348,38 @@ do_error (void *cls,
   GNUNET_asprintf (&json_error,
                    "{Error while processing request: %s}",
                    handle->emsg);
-  resp = GNUNET_REST_create_json_response (json_error);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  resp = GNUNET_REST_create_response (json_error);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
   cleanup_handle (handle);
   GNUNET_free (json_error);
 }
 
+/**
+ * Task run on timeout, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+
 /**
  * Task run on shutdown.  Cleans up everything.
  *
  * @param cls unused
- * @param tc scheduler context
  */
 static void
-do_cleanup_handle_delayed (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_cleanup_handle_delayed (void *cls)
 {
   struct RequestHandle *handle = cls;
-  cleanup_handle(handle);
+
+  cleanup_handle (handle);
 }
 
 
@@ -354,43 +390,54 @@ do_cleanup_handle_delayed (void *cls,
  */
 static void
 token_creat_cont (void *cls,
-                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket)
+                  const char *label,
+                  const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                  const struct GNUNET_IDENTITY_PROVIDER_Token *token)
 {
-  struct JsonApiResource *json_resource;
+  struct GNUNET_JSONAPI_Resource *json_resource;
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  json_t *token_ticket_json;
+  json_t *ticket_json;
+  json_t *token_json;
   char *ticket_str;
+  char *token_str;
   char *result_str;
-  
+
   if (NULL == ticket)
   {
     handle->emsg = GNUNET_strdup ("Error in token issue");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-    
-  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
-  json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
-                                                    "tmpid"); //TODO
+
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
+                                                    label);
   ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
-  token_ticket_json = json_string (ticket_str);
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+  token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
+  ticket_json = json_string (ticket_str);
+  token_json = json_string (token_str);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
                                          GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
-                                         token_ticket_json);
+                                         ticket_json);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                         GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TOKEN,
+                                         token_json);
   GNUNET_free (ticket_str);
-  json_decref (token_ticket_json);
-  GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
-  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
+  GNUNET_free (token_str);
+  json_decref (ticket_json);
+  json_decref (token_json);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
+  resp = GNUNET_REST_create_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle);
-
-
 }
 
+
 /**
  * Continueationf for token issue request
  *
@@ -399,13 +446,13 @@ token_creat_cont (void *cls,
  * @param cls the request handle
  */
 static void
-issue_token_cont (struct RestConnectionDataHandle *con,
+issue_token_cont (struct GNUNET_REST_RequestHandle *con,
                   const char *url,
                   void *cls)
 {
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   const char *egoname;
-  
+
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_HashCode key;
@@ -419,6 +466,7 @@ issue_token_cont (struct RestConnectionDataHandle *con,
   char *exp_str;
   char *nonce_str;
   char *scopes;
+  char *vattrs;
   uint64_t time;
   uint64_t nonce;
 
@@ -426,7 +474,7 @@ issue_token_cont (struct RestConnectionDataHandle *con,
                                                 GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "URL invalid: %s\n", handle->url);
-    resp = GNUNET_REST_create_json_response (NULL);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
     cleanup_handle (handle);
     return;
@@ -436,11 +484,12 @@ issue_token_cont (struct RestConnectionDataHandle *con,
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
                       strlen (GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST),
                       &key);
-  if ( GNUNET_YES ==
+  if ( GNUNET_YES !=
        GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
                                                &key) )
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Issuer not found\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               "Issuer not found\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
@@ -449,7 +498,9 @@ issue_token_cont (struct RestConnectionDataHandle *con,
   if (NULL == ego_val)
   {
     GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego invalid: %s\n", ego_val);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               "Ego invalid: %s\n",
+               ego_val);
     return;
   }
   for (ego_entry = handle->ego_head;
@@ -461,13 +512,18 @@ issue_token_cont (struct RestConnectionDataHandle *con,
     egoname = ego_entry->identifier;
     break;
   }
-  if (NULL == egoname || NULL == ego_entry)
+  if ( (NULL == egoname) ||
+       (NULL == ego_entry) )
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Ego not found: %s\n", ego_val);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               "Ego not found: %s\n",
+               ego_val);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego to issue token for: %s\n", egoname);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Ego to issue token for: %s\n",
+             egoname);
 
 
   //Meta info
@@ -487,6 +543,21 @@ issue_token_cont (struct RestConnectionDataHandle *con,
   scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                               &key);
 
+  //vattrs
+  GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST,
+                      strlen (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST),
+                      &key);
+
+  vattrs = NULL;
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    vattrs = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                &key);
+  }
+
+
 
   //Token audience
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
@@ -497,13 +568,16 @@ issue_token_cont (struct RestConnectionDataHandle *con,
        GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
                                                &key) )
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience missing!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Audience missing!\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                 &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience to issue token for: %s\n", audience);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Audience to issue token for: %s\n",
+              audience);
 
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
   GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
@@ -513,7 +587,7 @@ issue_token_cont (struct RestConnectionDataHandle *con,
                                  &aud_key,
                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
 
-  //Remote nonce 
+  //Remote nonce
   nonce_str = NULL;
   GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE,
                       strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE),
@@ -528,8 +602,11 @@ issue_token_cont (struct RestConnectionDataHandle *con,
   }
   nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                  &key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
-  sscanf (nonce_str, "%lu", &nonce);
+  GNUNET_assert (NULL != nonce_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Request nonce: %s\n",
+              nonce_str);
+  GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
 
   //Get expiration for token from URL parameter
   GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING,
@@ -565,6 +642,7 @@ issue_token_cont (struct RestConnectionDataHandle *con,
                                                          priv_key,
                                                          &aud_key,
                                                          scopes,
+                                                         vattrs,
                                                          exp_time,
                                                          nonce,
                                                          &token_creat_cont,
@@ -577,24 +655,32 @@ issue_token_cont (struct RestConnectionDataHandle *con,
  * Build a GNUid token for identity
  *
  * @param cls the request handle
- * @param tc task context
  */
 static void
-return_token_list (void *cls,
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+return_token_list (void *cls)
 {
   char* result_str;
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
 
-  GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_json_response (result_str);
+  resp = GNUNET_REST_create_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   cleanup_handle (handle);
 }
 
+
+static void
+token_collect_error_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  do_error (handle);
+}
+
+
 /**
  * Collect all tokens for an ego
  *
@@ -606,45 +692,68 @@ token_collect (void *cls,
                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
                const char *label,
                unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
+               const struct GNUNET_GNSRECORD_Data *rd);
+
+
+static void
+token_collect_finished_cb (void *cls)
 {
-  int i;
-  char* data;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_tmp;
-  struct JsonApiResource *json_resource;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  json_t *issuer;
-  json_t *token;
 
-  if (NULL == label)
-  {
-    ego_tmp = handle->ego_head;
-    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                 handle->ego_tail,
-                                 ego_tmp);
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-
-    if (NULL == handle->ego_head)
-    {
-      //Done
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
-      handle->ns_it = NULL;
-      GNUNET_SCHEDULER_add_now (&return_token_list, handle);
-      return;
-    }
+  ego_tmp = handle->ego_head;
+  GNUNET_CONTAINER_DLL_remove (handle->ego_head,
+                               handle->ego_tail,
+                               ego_tmp);
+  GNUNET_free (ego_tmp->identifier);
+  GNUNET_free (ego_tmp->keystring);
+  GNUNET_free (ego_tmp);
 
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Next ego: %s\n", handle->ego_head->identifier);
-    priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-    handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                           priv_key,
-                                                           &token_collect,
-                                                           handle);
+  if (NULL == handle->ego_head)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token END\n");
+    handle->ns_it = NULL;
+    GNUNET_SCHEDULER_add_now (&return_token_list, handle);
     return;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Next ego: %s\n",
+              handle->ego_head->identifier);
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+  handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                         priv_key,
+                                                         &token_collect_error_cb,
+                                                         handle,
+                                                         &token_collect,
+                                                         handle,
+                                                         &token_collect_finished_cb,
+                                                         handle);
+}
+
+
+/**
+ * Collect all tokens for an ego
+ *
+ * TODO move this into the identity-provider service
+ *
+ */
+static void
+token_collect (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+               const char *label,
+               unsigned int rd_count,
+               const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  int i;
+  char* data;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *issuer;
+  json_t *token;
+
   for (i = 0; i < rd_count; i++)
   {
     if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
@@ -653,20 +762,20 @@ token_collect (void *cls,
                                                rd[i].data,
                                                rd[i].data_size);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
-      json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                                        label);
+      json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                                   label);
       issuer = json_string (handle->ego_head->identifier);
-      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
-                                             issuer);
+      GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                        GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+                                        issuer);
       json_decref (issuer);
       token = json_string (data);
-      GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                             GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
-                                             token);
+      GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                        GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+                                        token);
       json_decref (token);
 
-      GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
+      GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
       GNUNET_free (data);
     }
   }
@@ -684,7 +793,7 @@ token_collect (void *cls,
  * @param cls the RequestHandle
  */
 static void
-list_token_cont (struct RestConnectionDataHandle *con_handle,
+list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
                  const char* url,
                  void *cls)
 {
@@ -709,6 +818,7 @@ list_token_cont (struct RestConnectionDataHandle *con_handle,
   }
   ego_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                &key);
+  GNUNET_assert (NULL != ego_val);
   //Remove non-matching egos
   for (ego_entry = handle->ego_head;
        NULL != ego_entry;)
@@ -725,7 +835,7 @@ list_token_cont (struct RestConnectionDataHandle *con_handle,
       GNUNET_free (ego_tmp);
     }
   }
-  handle->resp_object = GNUNET_REST_jsonapi_object_new ();
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   if (NULL == handle->ego_head)
   {
     //Done
@@ -737,7 +847,11 @@ list_token_cont (struct RestConnectionDataHandle *con_handle,
   handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
   handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
                                                          priv_key,
+                                                         &token_collect_error_cb,
+                                                         handle,
                                                          &token_collect,
+                                                         handle,
+                                                         &token_collect_finished_cb,
                                                          handle);
 
 }
@@ -750,27 +864,58 @@ list_token_cont (struct RestConnectionDataHandle *con_handle,
  */
 static void
 exchange_cont (void *cls,
-               const struct GNUNET_IDENTITY_PROVIDER_Token *token)
+               const struct GNUNET_IDENTITY_PROVIDER_Token *token,
+               uint64_t ticket_nonce)
 {
   json_t *root;
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
+  struct GNUNET_HashCode key;
   char* result;
   char* token_str;
+  char* nonce_str;
+  uint64_t expected_nonce;
+
+  //Get nonce
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE,
+                      strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_EXPECTED_NONCE),
+                      &key);
+
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->emsg = GNUNET_strdup ("No nonce given.");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+                                                 &key);
+  GNUNET_assert (NULL != nonce_str);
+  GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
+
+  if (ticket_nonce != expected_nonce)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Ticket nonce %"SCNu64" does not match expected nonce %"SCNu64"\n",
+                ticket_nonce, expected_nonce);
+    handle->emsg = GNUNET_strdup ("Ticket nonce does not match expected nonce\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
 
   root = json_object ();
   token_str = GNUNET_IDENTITY_PROVIDER_token_to_string (token);
-  json_object_set_new (root, "identity_token", json_string (token_str));
+  json_object_set_new (root, "token", json_string (token_str));
   json_object_set_new (root, "token_type", json_string ("jwt"));
   GNUNET_free (token_str);
 
   result = json_dumps (root, JSON_INDENT(1));
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", result);
-  resp = GNUNET_REST_create_json_response (result);
+  resp = GNUNET_REST_create_response (result);
   GNUNET_free (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   cleanup_handle (handle);
-  json_decref (root); 
+  json_decref (root);
 }
 
 
@@ -804,6 +949,7 @@ exchange_token_ticket_cb (void *cls,
     return;
   }
 
+  //Get ticket
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
                       strlen (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET),
                       &key);
@@ -818,7 +964,6 @@ exchange_token_ticket_cb (void *cls,
   }
   ticket_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
                                                   &key);
-
   handle->priv_key = GNUNET_IDENTITY_ego_get_private_key (ego);
   GNUNET_IDENTITY_PROVIDER_string_to_ticket (ticket_str,
                                              &ticket);
@@ -843,7 +988,7 @@ exchange_token_ticket_cb (void *cls,
  * @param cls the RequestHandle
  */
 static void
-exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
+exchange_token_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
                             const char* url,
                             void *cls)
 {
@@ -864,7 +1009,7 @@ exchange_token_ticket_cont (struct RestConnectionDataHandle *con_handle,
  * @param cls the RequestHandle
  */
 static void
-options_cont (struct RestConnectionDataHandle *con_handle,
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
               const char* url,
               void *cls)
 {
@@ -872,7 +1017,7 @@ options_cont (struct RestConnectionDataHandle *con_handle,
   struct RequestHandle *handle = cls;
 
   //For now, independent of path return all options
-  resp = GNUNET_REST_create_json_response (NULL);
+  resp = GNUNET_REST_create_response (NULL);
   MHD_add_response_header (resp,
                            "Access-Control-Allow-Methods",
                            allow_methods);
@@ -889,7 +1034,8 @@ options_cont (struct RestConnectionDataHandle *con_handle,
 static void
 init_cont (struct RequestHandle *handle)
 {
-  static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN_ISSUE, &issue_token_cont},
     //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont},
     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PROVIDER, &list_token_cont},
@@ -898,9 +1044,12 @@ init_cont (struct RequestHandle *handle)
     GNUNET_REST_HANDLER_END
   };
 
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
   {
-    handle->emsg = GNUNET_strdup ("Request unsupported");
+    handle->response_code = err.error_code;
     GNUNET_SCHEDULER_add_now (&do_error, handle);
   }
 }
@@ -957,10 +1106,10 @@ list_ego (void *cls,
   if (ID_REST_STATE_INIT == handle->state) {
     ego_entry = GNUNET_new (struct EgoEntry);
     GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring = 
+    ego_entry->keystring =
       GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
+    ego_entry->identifier = GNUNET_strdup (identifier);
     GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
   }
 
@@ -978,7 +1127,7 @@ list_ego (void *cls,
  * @return GNUNET_OK if request accepted
  */
 static void
-rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
                               GNUNET_REST_ResultProcessor proc,
                               void *proc_cls)
 {
@@ -991,7 +1140,7 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
   handle->conndata_handle = conndata_handle;
 
 
-  GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
+  handle->url = GNUNET_strdup (conndata_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1001,10 +1150,8 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
                                                      handle);
   handle->timeout_task =
     GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
+                                  &do_timeout,
                                   handle);
-
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Connected\n");
 }
@@ -1016,7 +1163,7 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
  * @return NULL on error, otherwise the plugin context
  */
 void *
-libgnunet_plugin_rest_identity_token_init (void *cls)
+libgnunet_plugin_rest_identity_provider_init (void *cls)
 {
   static struct Plugin plugin;
   struct GNUNET_REST_Plugin *api;
@@ -1051,7 +1198,7 @@ libgnunet_plugin_rest_identity_token_init (void *cls)
  * @return always NULL
  */
 void *
-libgnunet_plugin_rest_identity_token_done (void *cls)
+libgnunet_plugin_rest_identity_provider_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;