RECLAIM/REST: simplify auth code; include attrs
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 26 Apr 2019 12:47:29 +0000 (14:47 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 26 Apr 2019 12:47:29 +0000 (14:47 +0200)
src/reclaim/oidc_helper.c
src/reclaim/oidc_helper.h
src/reclaim/plugin_rest_openid_connect.c

index 331bd27116235eb108bec8473d466c8b240d833f..37387b5e0edb3b6851d3198c1c4e1bbb8924cec0 100644 (file)
@@ -52,7 +52,8 @@ static void
 replace_char (char *str, char find, char replace)
 {
   char *current_pos = strchr (str, find);
-  while (current_pos) {
+  while (current_pos)
+  {
     *current_pos = replace;
     current_pos = strchr (current_pos, find);
   }
@@ -84,7 +85,8 @@ 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)
+                   const char *nonce,
+                   const char *secret_key)
 {
   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
   struct GNUNET_HashCode signature;
@@ -110,9 +112,11 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   // nonce only if nonce
   // OPTIONAL acr,amr,azp
   subject = GNUNET_STRINGS_data_to_string_alloc (
-      sub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+    sub_key,
+    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
   audience = GNUNET_STRINGS_data_to_string_alloc (
-      aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+    aud_key,
+    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
   header = create_jwt_header ();
   body = json_object ();
 
@@ -125,21 +129,27 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   // 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_object_set_new (body,
+                       "iat",
                        json_integer (time_now.abs_value_us / (1000 * 1000)));
   // exp
-  json_object_set_new (body, "exp",
+  json_object_set_new (body,
+                       "exp",
                        json_integer (exp_time.abs_value_us / (1000 * 1000)));
   // nbf
-  json_object_set_new (body, "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);
+  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);
   }
@@ -160,14 +170,20 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
    * 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,
+  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,
+  GNUNET_asprintf (&result,
+                   "%s.%s.%s",
+                   header_base64,
+                   body_base64,
                    signature_base64);
 
   GNUNET_free (signature_target);
@@ -178,64 +194,125 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   GNUNET_free (header_base64);
   return result;
 }
+
+
+/**
+ * Returns base64 encoded string urlencoded
+ *
+ * @param string the string to encode
+ * @return base64 encoded string
+ */
+static char *
+base64_encode (const char *data,
+               size_t data_size)
+{
+  char *enc;
+  char *enc_urlencode;
+  char *tmp;
+  int i;
+  int num_pads = 0;
+
+  GNUNET_STRINGS_base64_encode (data, data_size, &enc);
+  tmp = strchr (enc, '=');
+  num_pads = strlen (enc) - (tmp - enc);
+  GNUNET_assert ((3 > num_pads) && (0 <= num_pads));
+  if (0 == num_pads)
+    return enc;
+  enc_urlencode = GNUNET_malloc (strlen (enc) + num_pads * 2);
+  strcpy (enc_urlencode, enc);
+  GNUNET_free (enc);
+  tmp = strchr (enc_urlencode, '=');
+  for (i = 0; i < num_pads; i++) {
+    strcpy (tmp, "%3D"); // replace '=' with '%3D'
+    tmp += 3;
+  }
+  return enc_urlencode;
+}
+
+
+
+
 /**
  * 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 attrs list of attributes whicha re shared
  * @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)
+                       struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                       const char *nonce_str)
 {
-  char *ticket_str;
-  json_t *code_json;
-  char *signature_payload;
-  char *signature_str;
-  char *authz_code;
+  char *code_payload;
+  char *attrs_ser;
+  char *code_str;
+  char *buf_ptr;
   size_t signature_payload_len;
+  size_t attr_list_len;
+  size_t code_payload_len;
+  unsigned int nonce;
+  unsigned int nonce_tmp;
   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;
+  attrs_ser = NULL;
+  signature_payload_len =
+    sizeof (struct GNUNET_RECLAIM_Ticket) + sizeof (unsigned int);
+  if (NULL != attrs)
+  {
+    attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
+    signature_payload_len += attr_list_len;
+    attrs_ser = GNUNET_malloc (attr_list_len);
+    GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, attrs_ser);
+  }
+  code_payload_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                     signature_payload_len + sizeof (signature);
+  code_payload = GNUNET_malloc (code_payload_len);
+  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_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 (((char *)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
-            nonce, strlen (nonce));
-  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, purpose, &signature)) {
-    GNUNET_free (signature_payload);
+  // First, copy ticket
+  buf_ptr = (char *) &purpose[1];
+  memcpy (buf_ptr, ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
+  buf_ptr += sizeof (struct GNUNET_RECLAIM_Ticket);
+  // Then copy nonce
+  nonce = 0;
+  if (NULL != nonce_str)
+  {
+    if ((1 != SSCANF (nonce_str, "%u", &nonce)) || (nonce > UINT16_MAX))
+    {
+      GNUNET_free (code_payload);
+      GNUNET_free_non_null (attrs_ser);
+      return NULL;
+    }
+  }
+  nonce_tmp = htons (nonce);
+  memcpy (buf_ptr, &nonce_tmp, sizeof (unsigned int));
+  buf_ptr += sizeof (unsigned int);
+  // Finally, attributes
+  if (NULL != attrs_ser)
+  {
+    memcpy (buf_ptr, attrs_ser, attr_list_len);
+    buf_ptr += attr_list_len;
+  }
+  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, purpose, &signature))
+  {
+    GNUNET_free (code_payload);
+    GNUNET_free_non_null (attrs_ser);
     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;
+  memcpy (buf_ptr, &signature, sizeof (signature));
+  code_str = base64_encode ((const char *) &code_payload,
+                            code_payload_len);
+  GNUNET_free (code_payload);
+  GNUNET_free_non_null (attrs_ser);
+  return code_str;
 }
 
 
@@ -247,99 +324,70 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
  * @param audience the expected audience of the code
  * @param code the string representation of the code
  * @param ticket where to store the ticket
+ * @param attrs the attributes in the code
  * @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)
+                       const char *code,
+                       struct GNUNET_RECLAIM_Ticket *ticket,
+                       struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs,
+                       char **nonce_str)
 {
-  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;
+  char *code_payload;
+  char *attrs_ser;
+  char *ptr;
   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 != GNUNET_memcmp (audience, &(*ticket)->audience)) {
-    GNUNET_free (purpose);
-    GNUNET_free (*ticket);
-    json_decref (code_json);
-    *ticket = NULL;
+  struct GNUNET_CRYPTO_EcdsaSignature *signature;
+  size_t code_payload_len;
+  size_t attrs_ser_len;
+  size_t signature_offset;
+  unsigned int nonce;
+
+  code_payload = NULL;
+  code_payload_len =
+    GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload);
+  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
+  attrs_ser_len = code_payload_len;
+  attrs_ser_len -= sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose);
+  *ticket = *((struct GNUNET_RECLAIM_Ticket*) &purpose[1]);
+  attrs_ser_len -= sizeof (struct GNUNET_RECLAIM_Ticket);
+  nonce = ntohs (((unsigned int *) &ticket[1]));
+  attrs_ser_len -= sizeof (unsigned int);
+  ptr = code_payload;
+  signature_offset =
+    code_payload_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
+  signature = (struct GNUNET_CRYPTO_EcdsaSignature *)&ptr[signature_offset];
+  attrs_ser_len -= sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
+  attrs_ser = ((char *) &ticket[1]) + sizeof (unsigned int);
+  *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, attrs_ser_len);
+  if (0 != GNUNET_memcmp (audience, &ticket->audience))
+  {
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (*attrs);
+    GNUNET_free (code_payload);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Audience in ticket does not match client!\n");
     return GNUNET_SYSERR;
   }
-  if (NULL != nonce_str)
-    memcpy (((char *)&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");
+                                  purpose,
+                                  signature,
+                                  &ticket->identity))
+  {
+    GNUNET_RECLAIM_ATTRIBUTE_list_destroy (*attrs);
+    GNUNET_free (code_payload);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
     return GNUNET_SYSERR;
   }
-  *nonce = GNUNET_strdup (nonce_str);
+  *nonce_str = NULL;
+  if (nonce != 0)
+    GNUNET_asprintf (nonce_str, "%u", nonce);
   return GNUNET_OK;
 }
 
+
 /**
  * Build a token response for a token request
  * TODO: Maybe we should add the scope here?
@@ -350,7 +398,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
  * @param token_response where to store the response
  */
 void
-OIDC_build_token_response (const char *access_token, const char *id_token,
+OIDC_build_token_response (const char *access_token,
+                           const char *id_token,
                            const struct GNUNET_TIME_Relative *expiration_time,
                            char **token_response)
 {
@@ -364,8 +413,9 @@ OIDC_build_token_response (const char *access_token, const char *id_token,
   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)));
+    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);
@@ -382,9 +432,10 @@ OIDC_access_token_new ()
   uint64_t random_number;
 
   random_number =
-      GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+    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);
+                                strlen (access_token_number),
+                                &access_token);
   return access_token;
 }
index d718b7a783f02f4f5509c0123bd5d75bbb2892eb..3c57dc235cdcae36150cd42a19f5fcaacda0a315 100644 (file)
@@ -11,7 +11,7 @@
       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/>.
 
@@ -62,12 +62,14 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
  *
  * @param issuer the issuer of the ticket, used to sign the ticket and nonce
  * @param ticket the ticket to include in the code
+ * @param attrs list of attributes to share
  * @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,
+                       struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
                        const char* nonce);
 
 /**
@@ -78,13 +80,15 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
  * @param audience the expected audience of the code
  * @param code the string representation of the code
  * @param ticket where to store the ticket
+ * @param attrs the attributes found in the code
  * @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,
+                       struct GNUNET_RECLAIM_Ticket *ticket,
+                       struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs,
                        char **nonce);
 
 /**
index 6cf1ffdee5acab4b6d510df1725b3b04f02bbf28..07cb55d79ca95dfbfbd362f8ce127f0d02271249 100644 (file)
@@ -676,37 +676,6 @@ return_userinfo_response (void *cls)
   cleanup_handle (handle);
 }
 
-/**
- * Returns base64 encoded string urlencoded
- *
- * @param string the string to encode
- * @return base64 encoded string
- */
-static char *
-base64_encode (const char *s)
-{
-  char *enc;
-  char *enc_urlencode;
-  char *tmp;
-  int i;
-  int num_pads = 0;
-
-  GNUNET_STRINGS_base64_encode (s, strlen (s), &enc);
-  tmp = strchr (enc, '=');
-  num_pads = strlen (enc) - (tmp - enc);
-  GNUNET_assert ((3 > num_pads) && (0 <= num_pads));
-  if (0 == num_pads)
-    return enc;
-  enc_urlencode = GNUNET_malloc (strlen (enc) + num_pads * 2);
-  strcpy (enc_urlencode, enc);
-  GNUNET_free (enc);
-  tmp = strchr (enc_urlencode, '=');
-  for (i = 0; i < num_pads; i++) {
-    strcpy (tmp, "%3D"); // replace '=' with '%3D'
-    tmp += 3;
-  }
-  return enc_urlencode;
-}
 
 /**
  * Respond to OPTIONS request
@@ -870,8 +839,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   struct MHD_Response *resp;
   char *ticket_str;
   char *redirect_uri;
-  char *code_json_string;
-  char *code_base64_final_string;
+  char *code_string;
 
   handle->idp_op = NULL;
   handle->ticket = *ticket;
@@ -884,20 +852,20 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   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 = OIDC_build_authz_code (&handle->priv_key, &handle->ticket,
+  code_string = OIDC_build_authz_code (&handle->priv_key, &handle->ticket,
+                                            handle->attr_list,
                                             handle->oidc->nonce);
-  code_base64_final_string = base64_encode (code_json_string);
   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, handle->tld,
                      handle->redirect_suffix, handle->oidc->response_type,
-                     code_base64_final_string, handle->oidc->state);
+                     code_string, handle->oidc->state);
   } else {
     GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s",
                      handle->oidc->redirect_uri, handle->oidc->response_type,
-                     code_base64_final_string, handle->oidc->state);
+                     code_string, handle->oidc->state);
   }
   resp = GNUNET_REST_create_response ("");
   MHD_add_response_header (resp, "Location", redirect_uri);
@@ -905,8 +873,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
   GNUNET_free (redirect_uri);
   GNUNET_free (ticket_str);
-  GNUNET_free (code_json_string);
-  GNUNET_free (code_base64_final_string);
+  GNUNET_free (code_string);
 }
 
 static void
@@ -1653,7 +1620,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url,
   }
 
   // decode code
-  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, &ticket, &nonce)) {
+  ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
+  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, 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;
@@ -1692,7 +1660,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url,
     return;
   }
   // 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);