gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [gnunet] branch master updated: refactoring of OIDC plugin


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated: refactoring of OIDC plugin
Date: Mon, 23 Jul 2018 12:42:24 +0200

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 97b5905aa refactoring of OIDC plugin
97b5905aa is described below

commit 97b5905aac2954fd0ce618b86ae80d11671fa1ba
Author: Schanzenbach, Martin <address@hidden>
AuthorDate: Mon Jul 23 12:42:18 2018 +0200

    refactoring of OIDC plugin
---
 src/reclaim/Makefile.am                  |   5 +-
 src/reclaim/jwt.c                        | 201 ------------
 src/reclaim/jwt.h                        |  23 --
 src/reclaim/oidc_helper.c                | 440 +++++++++++++++++++++++++
 src/reclaim/oidc_helper.h                | 109 +++++++
 src/reclaim/plugin_rest_openid_connect.c | 531 +++++++++++--------------------
 6 files changed, 737 insertions(+), 572 deletions(-)

diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
index 91a041f91..2ee43d21a 100644
--- a/src/reclaim/Makefile.am
+++ b/src/reclaim/Makefile.am
@@ -89,8 +89,7 @@ libgnunetreclaim_la_LDFLAGS = \
        -version-info 0:0:0
 
 libgnunet_plugin_rest_reclaim_la_SOURCES = \
-  plugin_rest_reclaim.c \
-       jwt.c
+  plugin_rest_reclaim.c
 libgnunet_plugin_rest_reclaim_la_LIBADD = \
        $(top_builddir)/src/identity/libgnunetidentity.la \
        libgnunetreclaim.la \
@@ -105,7 +104,7 @@ libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
 
 libgnunet_plugin_rest_openid_connect_la_SOURCES = \
   plugin_rest_openid_connect.c \
-       jwt.c
+       oidc_helper.c
 libgnunet_plugin_rest_openid_connect_la_LIBADD = \
        $(top_builddir)/src/identity/libgnunetidentity.la \
        libgnunetreclaim.la \
diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c
index 94db19b14..8b1378917 100644
--- a/src/reclaim/jwt.c
+++ b/src/reclaim/jwt.c
@@ -1,202 +1 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
 
-      GNUnet 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 Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      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/>.
- */
-
-/**
- * @file reclaim/jwt.c
- * @brief helper library for JSON-Web-Tokens
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_reclaim_attribute_lib.h"
-#include <jansson.h>
-
-
-#define JWT_ALG "alg"
-
-/* Use 512bit HMAC */
-#define JWT_ALG_VALUE "HS512"
-
-#define JWT_TYP "typ"
-
-#define JWT_TYP_VALUE "jwt"
-
-#define SERVER_ADDRESS "https://reclaim.id";
-
-static char*
-create_jwt_header(void)
-{
-  json_t *root;
-  char *json_str;
-
-  root = json_object ();
-  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
-  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
-
-  json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT);
-  json_decref (root);
-  return json_str;
-}
-
-static void
-replace_char(char* str, char find, char replace){
-  char *current_pos = strchr(str,find);
-  while (current_pos){
-    *current_pos = replace;
-    current_pos = strchr(current_pos,find);
-  }
-}
-
-//RFC4648
-static void
-fix_base64(char* str) {
-  char *padding;
-  //First, remove trailing padding '='
-  padding = strtok(str, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  //Replace + with -
-  replace_char (str, '+', '-');
-
-  //Replace / with _
-  replace_char (str, '/', '_');
-
-}
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the audience
- * @param sub_key the public key of the subject
- * @param attrs the attribute list
- * @param expiration_time the validity of the token
- * @param secret_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char*
-jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
-                      const struct GNUNET_TIME_Relative *expiration_time,
-                      const char *nonce,
-                      const char *secret_key)
-{
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_HashCode signature;
-  struct GNUNET_TIME_Absolute exp_time;
-  struct GNUNET_TIME_Absolute time_now;
-  char* audience;
-  char* subject;
-  char* header;
-  char* body_str;
-  char* result;
-  char* header_base64;
-  char* body_base64;
-  char* signature_target;
-  char* signature_base64;
-  char* attr_val_str;
-  json_t* body;
-  
-  //iat REQUIRED time now
-  time_now = GNUNET_TIME_absolute_get();
-  //exp REQUIRED time expired from config
-  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
-  //auth_time only if max_age
-  //nonce only if nonce
-  // OPTIONAL acr,amr,azp
-  subject = GNUNET_STRINGS_data_to_string_alloc (sub_key,
-                                                 sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
-                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
-  header = create_jwt_header ();
-  body = json_object ();
-
-  //iss REQUIRED case sensitive server uri with https
-  //The issuer is the local reclaim instance (e.g. 
https://reclaim.id/api/openid)
-  json_object_set_new (body,
-                       "iss", json_string (SERVER_ADDRESS));
-  //sub REQUIRED public key identity, not exceed 255 ASCII  length
-  json_object_set_new (body,
-                       "sub", json_string (subject));
-  //aud REQUIRED public key client_id must be there
-  json_object_set_new (body,
-                       "aud", json_string (audience));
-  //iat
-  json_object_set_new (body,
-                       "iat", json_integer (time_now.abs_value_us / 
(1000*1000)));
-  //exp
-  json_object_set_new (body,
-                       "exp", json_integer (exp_time.abs_value_us / 
(1000*1000)));
-  //nbf
-  json_object_set_new (body,
-                       "nbf", json_integer (time_now.abs_value_us / 
(1000*1000)));
-  //nonce
-  if (NULL != nonce)
-    json_object_set_new (body,
-                         "nonce", json_string (nonce));
-
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
-                                                             le->claim->data,
-                                                             
le->claim->data_size);
-    json_object_set_new (body,
-                         le->claim->name,
-                         json_string (attr_val_str));
-    GNUNET_free (attr_val_str);
-  }
-  body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT);
-  json_decref (body);
-
-  GNUNET_STRINGS_base64_encode (header,
-                                strlen (header),
-                                &header_base64);
-  fix_base64(header_base64);
-
-  GNUNET_STRINGS_base64_encode (body_str,
-                                strlen (body_str),
-                                &body_base64);
-  fix_base64(body_base64);
-
-  GNUNET_free (subject);
-  GNUNET_free (audience);
-
-  /**
-   * Creating the JWT signature. This might not be
-   * standards compliant, check.
-   */
-  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
-  GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, 
strlen (signature_target), &signature);
-  GNUNET_STRINGS_base64_encode ((const char*)&signature,
-                                sizeof (struct GNUNET_HashCode),
-                                &signature_base64);
-  fix_base64(signature_base64);
-
-  GNUNET_asprintf (&result, "%s.%s.%s",
-                   header_base64, body_base64, signature_base64);
-
-  GNUNET_free (signature_target);
-  GNUNET_free (header);
-  GNUNET_free (body_str);
-  GNUNET_free (signature_base64);
-  GNUNET_free (body_base64);
-  GNUNET_free (header_base64);
-  return result;
-}
diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h
deleted file mode 100644
index 12ff85b01..000000000
--- a/src/reclaim/jwt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef JWT_H
-#define JWT_H
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the audience
- * @param sub_key the public key of the subject
- * @param attrs the attribute list
- * @param expiration_time the validity of the token
- * @param nonce the nonce, may be NULL
- * @param secret_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char*
-jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                      const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
-                      const struct GNUNET_TIME_Relative *expiration_time,
-                      const char *nonce,
-                      const char *secret_key);
-
-#endif
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
new file mode 100644
index 000000000..9a99c5668
--- /dev/null
+++ b/src/reclaim/oidc_helper.c
@@ -0,0 +1,440 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet 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 Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      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/>.
+ */
+
+/**
+ * @file reclaim/oidc_helper.c
+ * @brief helper library for OIDC related functions
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_service.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "oidc_helper.h"
+
+static char*
+create_jwt_header(void)
+{
+  json_t *root;
+  char *json_str;
+
+  root = json_object ();
+  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+  json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (root);
+  return json_str;
+}
+
+static void
+replace_char(char* str, char find, char replace){
+  char *current_pos = strchr(str,find);
+  while (current_pos){
+    *current_pos = replace;
+    current_pos = strchr(current_pos,find);
+  }
+}
+
+//RFC4648
+static void
+fix_base64(char* str) {
+  char *padding;
+  //First, remove trailing padding '='
+  padding = strtok(str, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  //Replace + with -
+  replace_char (str, '+', '-');
+
+  //Replace / with _
+  replace_char (str, '/', '_');
+
+}
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param expiration_time the validity of the token
+ * @param secret_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                   const struct GNUNET_TIME_Relative *expiration_time,
+                   const char *nonce,
+                   const char *secret_key)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_HashCode signature;
+  struct GNUNET_TIME_Absolute exp_time;
+  struct GNUNET_TIME_Absolute time_now;
+  char* audience;
+  char* subject;
+  char* header;
+  char* body_str;
+  char* result;
+  char* header_base64;
+  char* body_base64;
+  char* signature_target;
+  char* signature_base64;
+  char* attr_val_str;
+  json_t* body;
+
+  //iat REQUIRED time now
+  time_now = GNUNET_TIME_absolute_get();
+  //exp REQUIRED time expired from config
+  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
+  //auth_time only if max_age
+  //nonce only if nonce
+  // OPTIONAL acr,amr,azp
+  subject = GNUNET_STRINGS_data_to_string_alloc (sub_key,
+                                                 sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
+                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  header = create_jwt_header ();
+  body = json_object ();
+
+  //iss REQUIRED case sensitive server uri with https
+  //The issuer is the local reclaim instance (e.g. 
https://reclaim.id/api/openid)
+  json_object_set_new (body,
+                       "iss", json_string (SERVER_ADDRESS));
+  //sub REQUIRED public key identity, not exceed 255 ASCII  length
+  json_object_set_new (body,
+                       "sub", json_string (subject));
+  //aud REQUIRED public key client_id must be there
+  json_object_set_new (body,
+                       "aud", json_string (audience));
+  //iat
+  json_object_set_new (body,
+                       "iat", json_integer (time_now.abs_value_us / 
(1000*1000)));
+  //exp
+  json_object_set_new (body,
+                       "exp", json_integer (exp_time.abs_value_us / 
(1000*1000)));
+  //nbf
+  json_object_set_new (body,
+                       "nbf", json_integer (time_now.abs_value_us / 
(1000*1000)));
+  //nonce
+  if (NULL != nonce)
+    json_object_set_new (body,
+                         "nonce", json_string (nonce));
+
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
+                                                             le->claim->data,
+                                                             
le->claim->data_size);
+    json_object_set_new (body,
+                         le->claim->name,
+                         json_string (attr_val_str));
+    GNUNET_free (attr_val_str);
+  }
+  body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (body);
+
+  GNUNET_STRINGS_base64_encode (header,
+                                strlen (header),
+                                &header_base64);
+  fix_base64(header_base64);
+
+  GNUNET_STRINGS_base64_encode (body_str,
+                                strlen (body_str),
+                                &body_base64);
+  fix_base64(body_base64);
+
+  GNUNET_free (subject);
+  GNUNET_free (audience);
+
+  /**
+   * Creating the JWT signature. This might not be
+   * standards compliant, check.
+   */
+  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
+  GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, 
strlen (signature_target), &signature);
+  GNUNET_STRINGS_base64_encode ((const char*)&signature,
+                                sizeof (struct GNUNET_HashCode),
+                                &signature_base64);
+  fix_base64(signature_base64);
+
+  GNUNET_asprintf (&result, "%s.%s.%s",
+                   header_base64, body_base64, signature_base64);
+
+  GNUNET_free (signature_target);
+  GNUNET_free (header);
+  GNUNET_free (body_str);
+  GNUNET_free (signature_base64);
+  GNUNET_free (body_base64);
+  GNUNET_free (header_base64);
+  return result;
+}
+/**
+ * Builds an OIDC authorization code including
+ * a reclaim ticket and nonce
+ *
+ * @param issuer the issuer of the ticket, used to sign the ticket and nonce
+ * @param ticket the ticket to include in the code
+ * @param nonce the nonce to include in the code
+ * @return a new authorization code (caller must free)
+ */
+char*
+OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+                       const struct GNUNET_RECLAIM_Ticket *ticket,
+                       const char* nonce)
+{
+  char *ticket_str;
+  json_t *code_json;
+  char *signature_payload;
+  char *signature_str;
+  char *authz_code;
+  size_t signature_payload_len;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+
+  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
+  if (NULL != nonce)
+    signature_payload_len += strlen (nonce);
+
+  signature_payload = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
+  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload;
+  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
signature_payload_len);
+  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
+  memcpy (&purpose[1],
+          ticket,
+          sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (NULL != nonce)
+    memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket),
+            nonce,
+            strlen (nonce));
+  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer,
+                                                 purpose,
+                                                 &signature))
+  {
+    GNUNET_free (signature_payload);
+    return NULL;
+  }
+  signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature,
+                                                       sizeof (signature));
+  ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                    sizeof (struct 
GNUNET_RECLAIM_Ticket));
+
+  code_json = json_object ();
+  json_object_set_new (code_json,
+                       "ticket",
+                       json_string (ticket_str));
+  if (NULL != nonce)
+    json_object_set_new (code_json,
+                         "nonce",
+                         json_string (nonce));
+  json_object_set_new (code_json,
+                       "signature",
+                       json_string (signature_str));
+  authz_code = json_dumps (code_json,
+                           JSON_INDENT(0) | JSON_COMPACT);
+  GNUNET_free (signature_payload);
+  GNUNET_free (signature_str);
+  GNUNET_free (ticket_str);
+  json_decref (code_json);
+  return authz_code;
+}
+
+
+
+
+/**
+ * Parse reclaim ticket and nonce from
+ * authorization code.
+ * This also verifies the signature in the code.
+ *
+ * @param audience the expected audience of the code
+ * @param code the string representation of the code
+ * @param ticket where to store the ticket
+ * @param nonce where to store the nonce
+ * @return GNUNET_OK if successful, else GNUNET_SYSERR
+ */
+int
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
+                       const char* code,
+                       struct GNUNET_RECLAIM_Ticket **ticket,
+                       char **nonce)
+{
+  json_error_t error;
+  json_t *code_json;
+  json_t *ticket_json;
+  json_t *nonce_json;
+  json_t *signature_json;
+  const char *ticket_str;
+  const char *signature_str;
+  const char *nonce_str;
+  char *code_output;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  size_t signature_payload_len;
+
+  code_output = NULL; 
+  GNUNET_STRINGS_base64_decode (code,
+                                strlen(code),
+                                (void**)&code_output);
+  code_json = json_loads (code_output, 0 , &error);
+  GNUNET_free (code_output);
+  ticket_json = json_object_get (code_json, "ticket");
+  nonce_json = json_object_get (code_json, "nonce");
+  signature_json = json_object_get (code_json, "signature");
+  *ticket = NULL;
+  *nonce = NULL;
+
+  if ((NULL == ticket_json || !json_is_string (ticket_json)) ||
+      (NULL == signature_json || !json_is_string (signature_json)))
+  {
+    json_decref (code_json);
+    return GNUNET_SYSERR;
+  }
+  ticket_str = json_string_value (ticket_json);
+  signature_str = json_string_value (signature_json);
+  nonce_str = NULL;
+  if (NULL != nonce_json)
+    nonce_str = json_string_value (nonce_json);
+  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
+  if (NULL != nonce_str)
+    signature_payload_len += strlen (nonce_str);
+  purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                           signature_payload_len);
+  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
signature_payload_len);
+  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str,
+                                                  strlen (ticket_str),
+                                                  &purpose[1],
+                                                  sizeof (struct 
GNUNET_RECLAIM_Ticket)))
+  {
+    GNUNET_free (purpose);
+    json_decref (code_json);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot parse ticket!\n");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str,
+                                                  strlen (signature_str),
+                                                  &signature,
+                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature)))
+  {
+    GNUNET_free (purpose);
+    json_decref (code_json);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot parse signature!\n");
+    return GNUNET_SYSERR;
+  }
+  *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
+  memcpy (*ticket,
+          &purpose[1],
+          sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (0 != memcmp (audience,
+                   &(*ticket)->audience,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    GNUNET_free (purpose);
+    GNUNET_free (*ticket);
+    json_decref (code_json);
+    *ticket = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Audience in ticket does not match client!\n");
+    return GNUNET_SYSERR;
+
+  }
+  if (NULL != nonce_str)
+    memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket),
+            nonce_str,
+            strlen (nonce_str));
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify 
(GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
+                                               purpose,
+                                               &signature,
+                                               &(*ticket)->identity))
+  {
+    GNUNET_free (purpose);
+    GNUNET_free (*ticket);
+    json_decref (code_json);
+    *ticket = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Signature of authZ code invalid!\n");
+    return GNUNET_SYSERR;
+  }
+  *nonce = GNUNET_strdup (nonce_str);
+  return GNUNET_OK;
+}
+
+/**
+ * Build a token response for a token request
+ * TODO: Maybe we should add the scope here?
+ *
+ * @param access_token the access token to include
+ * @param id_token the id_token to include
+ * @param expiration_time the expiration time of the token(s)
+ * @param token_response where to store the response
+ */
+void
+OIDC_build_token_response (const char *access_token,
+                           const char *id_token,
+                           const struct GNUNET_TIME_Relative *expiration_time,
+                           char **token_response)
+{
+  json_t *root_json;
+
+  root_json = json_object ();
+
+  GNUNET_assert (NULL != access_token);
+  GNUNET_assert (NULL != id_token);
+  GNUNET_assert (NULL != expiration_time);
+  json_object_set_new (root_json,
+                       "access_token",
+                       json_string (access_token));
+  json_object_set_new (root_json,
+                       "token_type",
+                       json_string ("Bearer"));
+  json_object_set_new (root_json,
+                       "expires_in",
+                       json_integer (expiration_time->rel_value_us / (1000 * 
1000)));
+  json_object_set_new (root_json,
+                       "id_token",
+                       json_string (id_token));
+  *token_response = json_dumps (root_json,
+                                JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (root_json);
+}
+
+/**
+ * Generate a new access token
+ */
+char*
+OIDC_access_token_new ()
+{
+  char* access_token_number;
+  char* access_token;
+  uint64_t random_number;
+
+  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, 
UINT64_MAX);
+  GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number);
+  
GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
+  return access_token;
+}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
new file mode 100644
index 000000000..7a0f45bf9
--- /dev/null
+++ b/src/reclaim/oidc_helper.h
@@ -0,0 +1,109 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet 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 Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      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/>.
+ */
+
+/**
+ * @file reclaim/oidc_helper.h
+ * @brief helper library for OIDC related functions
+ * @author Martin Schanzenbach
+ */
+
+#ifndef JWT_H
+#define JWT_H
+
+#define JWT_ALG "alg"
+
+/* Use 512bit HMAC */
+#define JWT_ALG_VALUE "HS512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
+
+#define SERVER_ADDRESS "https://reclaim.id";
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param expiration_time the validity of the token
+ * @param secret_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                   const struct GNUNET_TIME_Relative *expiration_time,
+                   const char *nonce,
+                   const char *secret_key);
+
+/**
+ * Builds an OIDC authorization code including
+ * a reclaim ticket and nonce
+ *
+ * @param issuer the issuer of the ticket, used to sign the ticket and nonce
+ * @param ticket the ticket to include in the code
+ * @param nonce the nonce to include in the code
+ * @return a new authorization code (caller must free)
+ */
+char*
+OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+                       const struct GNUNET_RECLAIM_Ticket *ticket,
+                       const char* nonce);
+
+/**
+ * Parse reclaim ticket and nonce from
+ * authorization code.
+ * This also verifies the signature in the code.
+ *
+ * @param audience the expected audience of the code
+ * @param code the string representation of the code
+ * @param ticket where to store the ticket
+ * @param nonce where to store the nonce
+ * @return GNUNET_OK if successful, else GNUNET_SYSERR
+ */
+int
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
+                       const char* code,
+                       struct GNUNET_RECLAIM_Ticket **ticket,
+                       char **nonce);
+
+/**
+ * Build a token response for a token request
+ * TODO: Maybe we should add the scope here?
+ *
+ * @param access_token the access token to include
+ * @param id_token the id_token to include
+ * @param expiration_time the expiration time of the token(s)
+ * @param token_response where to store the response
+ */
+void
+OIDC_build_token_response (const char *access_token,
+                           const char *id_token,
+                           const struct GNUNET_TIME_Relative *expiration_time,
+                           char **token_response);
+/**
+ * Generate a new access token
+ */
+char*
+OIDC_access_token_new ();
+
+
+#endif
diff --git a/src/reclaim/plugin_rest_openid_connect.c 
b/src/reclaim/plugin_rest_openid_connect.c
index 0f746f988..06815d9d1 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -38,7 +38,7 @@
 #include "gnunet_signatures.h"
 #include "gnunet_reclaim_attribute_lib.h"
 #include "gnunet_reclaim_service.h"
-#include "jwt.h"
+#include "oidc_helper.h"
 
 /**
  * REST root namespace
@@ -823,177 +823,6 @@ oidc_iteration_error (void *cls)
   GNUNET_SCHEDULER_add_now (&do_error, handle);
 }
 
-static int
-parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
-                  const char* code,
-                  struct GNUNET_RECLAIM_Ticket **ticket,
-                  char **nonce)
-{
-  json_error_t error;
-  json_t *code_json;
-  json_t *ticket_json;
-  json_t *nonce_json;
-  json_t *signature_json;
-  const char *ticket_str;
-  const char *signature_str;
-  const char *nonce_str;
-  char *code_output;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  size_t signature_payload_len;
-
-  code_output = NULL; 
-  GNUNET_STRINGS_base64_decode (code,
-                                strlen(code),
-                                (void**)&code_output);
-  code_json = json_loads (code_output, 0 , &error);
-  GNUNET_free (code_output);
-  ticket_json = json_object_get (code_json, "ticket");
-  nonce_json = json_object_get (code_json, "nonce");
-  signature_json = json_object_get (code_json, "signature");
-  *ticket = NULL;
-  *nonce = NULL;
-
-  if ((NULL == ticket_json || !json_is_string (ticket_json)) ||
-      (NULL == signature_json || !json_is_string (signature_json)))
-  {
-    json_decref (code_json);
-    return GNUNET_SYSERR;
-  }
-  ticket_str = json_string_value (ticket_json);
-  signature_str = json_string_value (signature_json);
-  nonce_str = NULL;
-  if (NULL != nonce_json)
-    nonce_str = json_string_value (nonce_json);
-  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
-  if (NULL != nonce_str)
-    signature_payload_len += strlen (nonce_str);
-  purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-                           signature_payload_len);
-  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
signature_payload_len);
-  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str,
-                                                  strlen (ticket_str),
-                                                  &purpose[1],
-                                                  sizeof (struct 
GNUNET_RECLAIM_Ticket)))
-  {
-    GNUNET_free (purpose);
-    json_decref (code_json);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot parse ticket!\n");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str,
-                                                  strlen (signature_str),
-                                                  &signature,
-                                                  sizeof (struct 
GNUNET_CRYPTO_EcdsaSignature)))
-  {
-    GNUNET_free (purpose);
-    json_decref (code_json);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot parse signature!\n");
-    return GNUNET_SYSERR;
-  }
-  *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
-  memcpy (*ticket,
-          &purpose[1],
-          sizeof (struct GNUNET_RECLAIM_Ticket));
-  if (0 != memcmp (audience,
-                   &(*ticket)->audience,
-                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    GNUNET_free (purpose);
-    GNUNET_free (*ticket);
-    json_decref (code_json);
-    *ticket = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Audience in ticket does not match client!\n");
-    return GNUNET_SYSERR;
-
-  }
-  if (NULL != nonce_str)
-    memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket),
-            nonce_str,
-            strlen (nonce_str));
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify 
(GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
-                                               purpose,
-                                               &signature,
-                                               &(*ticket)->identity))
-  {
-    GNUNET_free (purpose);
-    GNUNET_free (*ticket);
-    json_decref (code_json);
-    *ticket = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Signature of authZ code invalid!\n");
-    return GNUNET_SYSERR;
-  }
-  *nonce = GNUNET_strdup (nonce_str);
-  return GNUNET_OK;
-}
-
-static char*
-build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
-                  const struct GNUNET_RECLAIM_Ticket *ticket,
-                  const char* nonce)
-{
-  char *ticket_str;
-  json_t *code_json;
-  char *signature_payload;
-  char *signature_str;
-  char *authz_code;
-  size_t signature_payload_len;
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
-  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
-  if (NULL != nonce)
-    signature_payload_len += strlen (nonce);
-
-  signature_payload = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
-  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload;
-  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
signature_payload_len);
-  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
-  memcpy (&purpose[1],
-          ticket,
-          sizeof (struct GNUNET_RECLAIM_Ticket));
-  if (NULL != nonce)
-    memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket),
-            nonce,
-            strlen (nonce));
-  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer,
-                                                 purpose,
-                                                 &signature))
-  {
-    GNUNET_free (signature_payload);
-    return NULL;
-  }
-  signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature,
-                                                       sizeof (signature));
-  ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
-                                                    sizeof (struct 
GNUNET_RECLAIM_Ticket));
-
-  code_json = json_object ();
-  json_object_set_new (code_json,
-                       "ticket",
-                       json_string (ticket_str));
-  if (NULL != nonce)
-    json_object_set_new (code_json,
-                         "nonce",
-                         json_string (nonce));
-  json_object_set_new (code_json,
-                       "signature",
-                       json_string (signature_str));
-  authz_code = json_dumps (code_json,
-                           JSON_INDENT(0) | JSON_COMPACT);
-  GNUNET_free (signature_payload);
-  GNUNET_free (signature_str);
-  GNUNET_free (ticket_str);
-  json_decref (code_json);
-  return authz_code;
-}
-
-
 static void
 get_client_name_result (void *cls,
                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
@@ -1011,9 +840,9 @@ get_client_name_result (void *cls,
   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)
-  code_json_string = build_authz_code (&handle->priv_key,
-                                       &handle->ticket,
-                                       handle->oidc->nonce);
+  code_json_string = OIDC_build_authz_code (&handle->priv_key,
+                                            &handle->ticket,
+                                            handle->oidc->nonce);
   code_base64_final_string = base_64_encode(code_json_string);
   GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
                    handle->redirect_prefix,
@@ -1532,36 +1361,19 @@ login_cont (struct GNUNET_REST_RequestHandle 
*con_handle,
   return;
 }
 
-/**
- * Responds to token url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                const char* url,
-                void *cls)
+static int 
+check_authorization (struct RequestHandle *handle,
+                     struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
 {
-  //TODO static strings
-  struct RequestHandle *handle = cls;
   struct GNUNET_HashCode cache_key;
-  char *authorization, *credentials;
-  char delimiter[]=" ";
-  char delimiter_user_psw[]=":";
-  char *grant_type, *code;
-  char *user_psw = NULL, *client_id, *psw;
-  char *expected_psw;
+  char *authorization;
+  char *credentials;
+  char *basic_authorization;
+  char *client_id;
+  char *pass;
+  char *expected_pass;
   int client_exists = GNUNET_NO;
-  struct MHD_Response *resp;
-  char *json_response;
-  char *jwt_secret;
-  char *nonce;
 
-  /*
-   * Check Authorization
-   */
   GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
                       strlen (OIDC_AUTHORIZATION_HEADER_KEY),
                       &cache_key);
@@ -1571,80 +1383,75 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->edesc=GNUNET_strdup("missing authorization");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
-  authorization = GNUNET_CONTAINER_multihashmap_get ( 
handle->rest_handle->header_param_map, &cache_key);
+  authorization = GNUNET_CONTAINER_multihashmap_get 
(handle->rest_handle->header_param_map,
+                                                     &cache_key);
 
   //split header in "Basic" and [content]
-  credentials = strtok (authorization, delimiter);
-  if (0 != strcmp ("Basic",credentials))
+  credentials = strtok (authorization, " ");
+  if (0 != strcmp ("Basic", credentials))
   {
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
-  credentials = strtok(NULL, delimiter);
+  credentials = strtok(NULL, " ");
   if (NULL == credentials)
   {
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
-  GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), 
(void**)&user_psw);
+  GNUNET_STRINGS_base64_decode (credentials,
+                                strlen (credentials),
+                                (void**)&basic_authorization);
 
-  if ( NULL == user_psw )
+  if ( NULL == basic_authorization )
   {
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
-  client_id = strtok (user_psw, delimiter_user_psw);
+  client_id = strtok (basic_authorization, ":");
   if ( NULL == client_id )
   {
-    GNUNET_free_non_null(user_psw);
+    GNUNET_free_non_null(basic_authorization);
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
-  psw = strtok (NULL, delimiter_user_psw);
-  if (NULL == psw)
+  pass = strtok (NULL, ":");
+  if (NULL == pass)
   {
-    GNUNET_free_non_null(user_psw);
+    GNUNET_free_non_null(basic_authorization);
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
 
   //check client password
   if ( GNUNET_OK
        == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
-                                                 "psw", &expected_psw) )
+                                                 "psw", &expected_pass) )
   {
-    if (0 != strcmp (expected_psw, psw))
+    if (0 != strcmp (expected_pass, pass))
     {
-      GNUNET_free_non_null(user_psw);
-      GNUNET_free(expected_psw);
+      GNUNET_free_non_null(basic_authorization);
+      GNUNET_free(expected_pass);
       handle->emsg=GNUNET_strdup("invalid_client");
       handle->response_code = MHD_HTTP_UNAUTHORIZED;
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
+      return GNUNET_SYSERR;
     }
-    GNUNET_free(expected_psw);
+    GNUNET_free(expected_pass);
   }
   else
   {
-    GNUNET_free_non_null(user_psw);
+    GNUNET_free_non_null(basic_authorization);
     handle->emsg = GNUNET_strdup("server_error");
     handle->edesc = GNUNET_strdup ("gnunet configuration failed");
     handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    return GNUNET_SYSERR;
   }
 
   //check client_id
@@ -1659,9 +1466,108 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   }
   if (GNUNET_NO == client_exists)
   {
-    GNUNET_free_non_null(user_psw);
+    GNUNET_free_non_null(basic_authorization);
     handle->emsg=GNUNET_strdup("invalid_client");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  GNUNET_STRINGS_string_to_data (client_id,
+                                 strlen(client_id),
+                                 cid,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  GNUNET_free (client_id);
+  GNUNET_free (basic_authorization);
+  return GNUNET_OK;
+}
+
+static int
+ego_exists (struct RequestHandle *handle,
+            struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
+{
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+
+  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = 
ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
+    if (0 == memcmp (&pub_key,
+                     test_key,
+                     sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+    {
+      break;
+    }
+  }
+  if (NULL == ego_entry)
+    return GNUNET_NO;
+  return GNUNET_YES;
+}
+
+static void
+store_ticket_reference (const struct RequestHandle *handle,
+                        const char* access_token,
+                        const struct GNUNET_RECLAIM_Ticket *ticket,
+                        const struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
+{
+  struct GNUNET_HashCode cache_key;
+  char *id_ticket_combination;
+  char *ticket_string;
+  char *client_id;
+
+  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
+  client_id = GNUNET_STRINGS_data_to_string_alloc (cid,
+                                                   sizeof (struct 
GNUNET_CRYPTO_EcdsaPublicKey));
+  ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                       sizeof (struct 
GNUNET_RECLAIM_Ticket));
+  GNUNET_asprintf(&id_ticket_combination,
+                  "%s;%s",
+                  client_id,
+                  ticket_string);
+  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
+                                    &cache_key,
+                                    id_ticket_combination,
+                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+  GNUNET_free (client_id);
+  GNUNET_free (ticket_string);
+}
+
+/**
+ * Responds to token url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                const char* url,
+                void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_TIME_Relative expiration_time;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; 
+  struct GNUNET_RECLAIM_Ticket *ticket;
+  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
+  struct GNUNET_HashCode cache_key;
+  struct MHD_Response *resp;
+  char *grant_type;
+  char *code;
+  char *json_response;
+  char *id_token;
+  char *access_token;
+  char *jwt_secret;
+  char *nonce;
+  int i = 1;
+
+  /*
+   * Check Authorization
+   */
+  if (GNUNET_SYSERR == check_authorization (handle,
+                                            &cid))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "OIDC authorization for token endpoint failed\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
@@ -1673,27 +1579,25 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   //TODO Do not allow multiple equal parameter names
   //REQUIRED grant_type
   GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), 
&cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  
handle->rest_handle->url_param_map, &cache_key) )
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                              &cache_key))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("missing parameter grant_type");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  grant_type = GNUNET_CONTAINER_multihashmap_get (
-                                                  
handle->rest_handle->url_param_map, &cache_key);
+  grant_type = GNUNET_CONTAINER_multihashmap_get 
(handle->rest_handle->url_param_map,
+                                                  &cache_key);
 
   //REQUIRED code
   GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  
handle->rest_handle->url_param_map, &cache_key) )
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                              &cache_key))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("missing parameter code");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
@@ -1706,11 +1610,10 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   //REQUIRED redirect_uri
   GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
                       &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  
handle->rest_handle->url_param_map, &cache_key) )
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains 
(handle->rest_handle->url_param_map,
+                                              &cache_key) )
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
@@ -1721,21 +1624,18 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   //Check parameter grant_type == "authorization_code"
   if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg=GNUNET_strdup("unsupported_grant_type");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   GNUNET_CRYPTO_hash (code, strlen (code), &cache_key);
-  int i = 1;
-  if ( GNUNET_SYSERR
-       == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
-                                             &cache_key,
-                                             &i,
-                                             
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
+  if (GNUNET_SYSERR ==
+      GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
+                                         &cache_key,
+                                         &i,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
@@ -1744,18 +1644,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   }
 
   //decode code
-  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
-  GNUNET_STRINGS_string_to_data (client_id,
-                                 strlen(client_id),
-                                 &cid,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  struct GNUNET_RECLAIM_Ticket *ticket;
-  if(GNUNET_OK != parse_authz_code (&cid,
-                                    code,
-                                    &ticket,
-                                    &nonce))
+  if(GNUNET_OK != OIDC_parse_authz_code (&cid,
+                                         code,
+                                         &ticket,
+                                         &nonce))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("invalid code");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
@@ -1763,27 +1656,13 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
     return;
   }
 
-  // this is the current client (relying party)
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-  GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key);
-  if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct 
GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    GNUNET_free_non_null(user_psw);
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-
   //create jwt
-  struct GNUNET_TIME_Relative expiration_time;
-  if ( GNUNET_OK
-       != GNUNET_CONFIGURATION_get_value_time(cfg, "reclaim-rest-plugin",
-                                              "expiration_time", 
&expiration_time) )
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time(cfg,
+                                          "reclaim-rest-plugin",
+                                          "expiration_time",
+                                          &expiration_time))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("server_error");
     handle->edesc = GNUNET_strdup ("gnunet configuration failed");
     handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
@@ -1792,34 +1671,21 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
     return;
   }
 
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct 
GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
 
   //TODO OPTIONAL acr,amr,azp
-
-  struct EgoEntry *ego_entry;
-  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = 
ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
-    if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct 
GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      break;
-    }
-  }
-  if ( NULL == ego_entry )
+  if (GNUNET_NO == ego_exists (handle,
+                               &ticket->audience))
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("invalid code...");
     handle->response_code = MHD_HTTP_BAD_REQUEST;
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     GNUNET_free(ticket);
-    return;
   }
   if ( GNUNET_OK
        != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
                                                  "jwt_secret", &jwt_secret) )
   {
-    GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
     handle->edesc = GNUNET_strdup("No signing secret configured!");
     handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
@@ -1827,56 +1693,31 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
     GNUNET_free(ticket);
     return;
   }
-  char *id_token = jwt_create_from_list(&ticket->audience,
-                                        &ticket->identity,
-                                        cl,
-                                        &expiration_time,
-                                        (NULL != nonce) ? nonce : NULL,
-                                        jwt_secret);
-
-  //Create random access_token
-  char* access_token_number;
-  char* access_token;
-  uint64_t random_number;
-  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, 
UINT64_MAX);
-  GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number);
-  
GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
-
-
-
-  //TODO OPTIONAL add refresh_token and scope
-  GNUNET_asprintf (&json_response,
-                   "{ \"access_token\" : \"%s\", "
-                   "\"token_type\" : \"Bearer\", "
-                   "\"expires_in\" : %d, "
-                   "\"id_token\" : \"%s\"}",
-                   access_token,
-                   expiration_time,
-                   id_token);
-  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
-  char *id_ticket_combination;
-  char *ticket_string;
-  ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket,
-                                                       sizeof (struct 
GNUNET_RECLAIM_Ticket));
-  GNUNET_asprintf(&id_ticket_combination,
-                  "%s;%s",
-                  client_id,
-                  ticket_string);
-  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
-                                    &cache_key,
-                                    id_ticket_combination,
-                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
+  //TODO We should collect the attributes here. cl always empty
+  cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  id_token = OIDC_id_token_new (&ticket->audience,
+                                &ticket->identity,
+                                cl,
+                                &expiration_time,
+                                (NULL != nonce) ? nonce : NULL,
+                                jwt_secret);
+  access_token = OIDC_access_token_new (); 
+  OIDC_build_token_response (access_token,
+                             id_token,
+                             &expiration_time,
+                             &json_response);
+
+  store_ticket_reference (handle,
+                          access_token,
+                          ticket,
+                          &cid);
   resp = GNUNET_REST_create_response (json_response);
   MHD_add_response_header (resp, "Cache-Control", "no-store");
   MHD_add_response_header (resp, "Pragma", "no-cache");
   MHD_add_response_header (resp, "Content-Type", "application/json");
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-
   GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl);
-  GNUNET_free(access_token_number);
   GNUNET_free(access_token);
-  GNUNET_free(user_psw);
   GNUNET_free(json_response);
   GNUNET_free(ticket);
   GNUNET_free(id_token);

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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