change JWT algorithm to HMAC
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Thu, 19 Jul 2018 20:16:00 +0000 (22:16 +0200)
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Thu, 19 Jul 2018 20:16:00 +0000 (22:16 +0200)
src/identity-provider/identity-provider.conf
src/identity-provider/jwt.c
src/identity-provider/jwt.h
src/identity-provider/plugin_rest_openid_connect.c

index cc50152a1e48ec255542b4ffd94eb2ebadb1132c..99c0a50be07042f79bc8f7e55154d7c158c0f516 100644 (file)
@@ -16,6 +16,7 @@ DATABASE = sqlite
 #ADDRESS = https://identity.gnu:8000#/login
 ADDRESS = https://reclaim.ui/#/login
 PSW = secret
+JWT_SECRET = secret
 EXPIRATION_TIME = 3600
 
 [identity-provider-sqlite]
index 1a984f7b53eed109426c75bd2d573805b2d93517..7ac4f0025bce2d5e378c259dd622cee6a8e1ac21 100644 (file)
 
 #define JWT_ALG "alg"
 
-/*TODO is this the correct way to define new algs? */
-#define JWT_ALG_VALUE "urn:org:gnunet:jwt:alg:ecdsa:ed25519"
+/* Use 512bit HMAC */
+#define JWT_ALG_VALUE "HS512"
 
 #define JWT_TYP "typ"
 
 #define JWT_TYP_VALUE "jwt"
 
-//TODO change server address
-#define SERVER_ADDRESS "https://localhost"
+#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo"
 
 static char*
 create_jwt_header(void)
@@ -65,13 +64,12 @@ create_jwt_header(void)
  */
 char*
 jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
                                                 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
+                                                const struct GNUNET_CRYPTO_AuthKey *priv_key)
 {
   struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_CRYPTO_EcdsaPublicKey sub_key;
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_HashCode signature;
   char* audience;
   char* subject;
   char* header;
@@ -90,32 +88,25 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   //auth_time only if max_age
   //nonce only if nonce
   // OPTIONAL acr,amr,azp
-  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &sub_key);
-  /* TODO maybe we should use a local identity here */
   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 ();
-  /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
+  
   //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));
-  /* TODO what should be in here exactly? */
   //aud REQUIRED public key client_id must be there
   json_object_set_new (body,
                        "aud", json_string (audience));
   for (le = attrs->list_head; NULL != le; le = le->next)
   {
-    /**
-     * TODO here we should have a function that
-     * calls the Attribute plugins to create a
-     * json representation for its value
-     */
     attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
                                                               le->claim->data,
                                                               le->claim->data_size);
@@ -148,32 +139,13 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   GNUNET_free (audience);
 
   /**
-   * TODO
    * Creating the JWT signature. This might not be
    * standards compliant, check.
    */
   GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
-
-  purpose =
-    GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-                   strlen (signature_target));
-  purpose->size =
-    htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
-  purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
-                                             purpose,
-                                             (struct GNUNET_CRYPTO_EcdsaSignature *)&signature))
-  {
-    GNUNET_free (signature_target);
-    GNUNET_free (body_str);
-    GNUNET_free (body_base64);
-    GNUNET_free (header_base64);
-    GNUNET_free (purpose);
-    return NULL;
-  }
+  GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature);
   GNUNET_STRINGS_base64_encode ((const char*)&signature,
-                                sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+                                sizeof (struct GNUNET_HashCode),
                                 &signature_base64);
   GNUNET_asprintf (&result, "%s.%s.%s",
                    header_base64, body_base64, signature_base64);
@@ -184,6 +156,5 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   GNUNET_free (signature_base64);
   GNUNET_free (body_base64);
   GNUNET_free (header_base64);
-  GNUNET_free (purpose);
   return result;
 }
index 0729589730246b2ff80858ea8dcce0cdfcd52eec..80b6caa334680d34478b869debe3356d5f0a5fc5 100644 (file)
@@ -3,7 +3,8 @@
 
 char*
 jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                      const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
                                                 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
-                                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key);
+                                                const struct GNUNET_CRYPTO_AuthKey *priv_key);
 
 #endif
index 9c2f7fb3dbd6fa1e4dd988936fd8210c722accc4..cc4b83dae71b6f2fa2b468e7bd6ee1f341c80182 100644 (file)
@@ -1412,6 +1412,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   json_t *root, *ticket_string, *nonce, *max_age;
   json_error_t error;
   char *json_response;
+  char *jwt_secret;
 
   /*
    * Check Authorization
@@ -1447,7 +1448,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), &user_psw);
+  GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw);
 
   if ( NULL == user_psw )
   {
@@ -1598,7 +1599,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   //decode code
-  GNUNET_STRINGS_base64_decode(code,strlen(code),&code_output);
+  GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output);
   root = json_loads (code_output, 0, &error);
   GNUNET_free(code_output);
   ticket_string = json_object_get (root, "ticket");
@@ -1717,15 +1718,32 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   {
     GNUNET_free_non_null(user_psw);
     handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code....");
+    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, "identity-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;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+  struct GNUNET_CRYPTO_AuthKey jwt_sign_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk);
+  GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key);
   char *id_token = jwt_create_from_list(&ticket->audience,
+                                        &pk,
                                         cl,
-                                        GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego));
+                                        &jwt_sign_key);
 
   //Create random access_token
   char* access_token_number;