summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Schwieren <tristan.schwieren@tum.de>2022-04-13 16:58:26 +0200
committerTristan Schwieren <tristan.schwieren@tum.de>2022-04-13 16:58:26 +0200
commitf48ac31b79972dc427c67b911d386e953bafaae7 (patch)
treec51fbbc9ff61869cdefdf15f20cec3a3083eed94
parentd1d7070965e554470384304b8f66021a81d1bf9d (diff)
-messy attempt using JWS
-rw-r--r--src/reclaim/oidc_helper.c95
-rw-r--r--src/reclaim/oidc_helper.h10
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c222
3 files changed, 227 insertions, 100 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 9237902ce..ff34e045e 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -26,6 +26,7 @@
#include "platform.h"
#include <inttypes.h>
#include <jansson.h>
+#include <jose/jose.h>
#include "gnunet_util_lib.h"
#include "gnunet_reclaim_lib.h"
#include "gnunet_reclaim_service.h"
@@ -355,6 +356,100 @@ OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key,
return body_str;
}
+/**
+ * Create a JWT from attributes
+ * TODO: separate creation of body in OIDC_generate_id_token*
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param presentations credential presentation list (may be empty)
+ * @param expiration_time the validity of the token
+ * @param secret_rsa_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char *
+OIDC_generate_id_token_rsa (const struct GNUNET_IDENTITY_PublicKey *aud_key,
+ const struct GNUNET_IDENTITY_PublicKey *sub_key,
+ const struct GNUNET_RECLAIM_AttributeList *attrs,
+ const struct
+ GNUNET_RECLAIM_PresentationList *presentations,
+ const struct GNUNET_TIME_Relative *expiration_time,
+ const char *nonce,
+ const json_t *secret_rsa_key)
+{
+ struct GNUNET_HashCode signature;
+ struct GNUNET_TIME_Absolute exp_time;
+ struct GNUNET_TIME_Absolute time_now;
+ char *audience;
+ char *subject;
+ char *body_str; // REMOVE
+ char *result;
+ json_t *body;
+
+ body = generate_userinfo_json (sub_key,
+ attrs,
+ presentations);
+ // 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_IDENTITY_PublicKey));
+ audience =
+ GNUNET_STRINGS_data_to_string_alloc (aud_key,
+ sizeof(struct
+ GNUNET_IDENTITY_PublicKey));
+
+ // 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));
+
+ body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT); // REMOVE
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str); // REMOVE
+
+ GNUNET_free (subject);
+ GNUNET_free (audience);
+
+ /**
+ * Creating the JWT signature.
+ */
+ char *str = "Hallo Welt!";
+ json_t *jws = json_pack ("{s:o}", "payload",
+ jose_b64_enc (str, strlen (str)));
+ jose_jws_sig (NULL, jws, NULL, secret_rsa_key);
+
+ str = json_dumps (jws, JSON_INDENT (2) | JSON_COMPACT); // REMOVE
+ printf ("jwk_json: %s\n", str); // REMOVE
+
+ GNUNET_asprintf (&str, "%s.%s.%s",
+ json_string_value (json_object_get (jws, "protected")),
+ json_string_value (json_object_get (jws, "payload")),
+ json_string_value (json_object_get (jws, "signature")) );
+
+ printf ("jwk: %s\n", str);
+
+ return str;
+}
/**
* Create a JWT from attributes
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 2a8b7bbae..0a2f832ad 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -51,6 +51,16 @@ enum OIDC_VerificationOptions
OIDC_VERIFICATION_NO_CODE_VERIFIER = 1
};
+char *
+OIDC_generate_id_token_rsa (const struct GNUNET_IDENTITY_PublicKey *aud_key,
+ const struct GNUNET_IDENTITY_PublicKey *sub_key,
+ const struct GNUNET_RECLAIM_AttributeList *attrs,
+ const struct
+ GNUNET_RECLAIM_PresentationList *presentations,
+ const struct GNUNET_TIME_Relative *expiration_time,
+ const char *nonce,
+ const json_t *secret_rsa_key);
+
/**
* Create a JWT from attributes
*
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 4da8a2de7..17b707e7e 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -239,11 +239,6 @@
#define OIDC_JWK_RSA_FILENAME "jwk_rsa.json"
/**
- * OIDC key store file name length
- */
-#define OIDC_JWK_RSA_FILENAME_LEN strlen (OIDC_JWK_RSA_FILENAME)
-
-/**
* How long to wait for a consume in userinfo endpoint
*/
#define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
@@ -880,6 +875,103 @@ cookie_identity_interpretation (struct RequestHandle *handle)
/**
+ * @brief Read the the JSON Web Key in the given file and return it.
+ * Return NULL and emit warning if JSON can not be decoded or the key is
+ * invalid
+ *
+ * @param filename the file to read the JWK from
+ * @return json_t* the reed JWK
+ */
+json_t *
+read_jwk_from_file (const char *filename)
+{
+ json_t *jwk;
+ json_error_t error;
+
+ jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
+
+ if (! jwk)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ ("Could not read OIDC RSA key from config file; %s\n"),
+ error.text);
+ }
+
+ return jwk;
+}
+
+/**
+ * @brief Write the JWK to file. If unsuccessful emit warning
+ *
+ * @param filename the name of the file the JWK is writen to
+ * @param jwk the JWK that is going to be written
+ * @return int Return GNUNET_OK if write is sucessfull
+ */
+static int
+write_jwk_to_file (const char *filename,
+ json_t *jwk)
+{
+ if (json_dump_file (jwk, filename, JSON_INDENT (2)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ ("Could not write OIDC RSA key to file %s\n"),
+ filename);
+ return GNUNET_ERROR_TYPE_WARNING;
+ }
+ else
+ return GNUNET_OK;
+}
+
+/**
+ * @brief Generate a new RSA JSON Web Key
+ *
+ * @return json_t* the generated JWK
+ */
+json_t *
+generate_jwk ()
+{
+ json_t *jwk;
+ jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
+ jose_jwk_gen (NULL, jwk);
+ json_incref (jwk);
+ return jwk;
+}
+
+/**
+ * Return the path to the RSA JWK key file
+ *
+ * @param cls the RequestHandle
+ */
+char *
+get_oidc_jwk_path (void *cls)
+{
+ char *oidc_directory;
+ char *oidc_jwk_path;
+ struct RequestHandle *handle = cls;
+
+ // Read OIDC directory from config
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "reclaim-rest-plugin",
+ "oidc_dir",
+ &oidc_directory))
+ {
+ // Could not read Config file
+ handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_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 NULL;
+ }
+
+ // Create path to file
+ GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
+ OIDC_JWK_RSA_FILENAME);
+
+ return oidc_jwk_path;
+}
+
+
+/**
* Redirects to login page stored in configuration file
*/
static void
@@ -2071,6 +2163,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
char *jwt_secret;
char *nonce = NULL;
char *code_verifier;
+ json_t *oidc_jwk;
+ char *oidc_jwk_path;
/*
* Check Authorization
@@ -2195,13 +2289,26 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- id_token = OIDC_generate_id_token (&ticket.audience,
- &ticket.identity,
- cl,
- pl,
- &expiration_time,
- (NULL != nonce) ? nonce : NULL,
- jwt_secret);
+ // id_token = OIDC_generate_id_token (&ticket.audience,
+ // &ticket.identity,
+ // cl,
+ // pl,
+ // &expiration_time,
+ // (NULL != nonce) ? nonce : NULL,
+ // jwt_secret);
+
+ // Replace for now
+ // TODO: Add some kind of option for HMAC vs. RSA
+ oidc_jwk_path = get_oidc_jwk_path (cls);
+ oidc_jwk = read_jwk_from_file (oidc_jwk_path);
+ id_token = OIDC_generate_id_token_rsa (&ticket.audience,
+ &ticket.identity,
+ cl,
+ pl,
+ &expiration_time,
+ (NULL != nonce) ? nonce : NULL,
+ oidc_jwk);
+
GNUNET_free (jwt_secret);
if (NULL != nonce)
GNUNET_free (nonce);
@@ -2496,69 +2603,6 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
}
/**
- * @brief Read the the JSON Web Key in the given file and return it.
- * Return NULL and emit warning if JSON can not be decoded or the key is
- * invalid
- *
- * @param filename the file to read the JWK from
- * @return json_t* the reed JWK
- */
-json_t *
-read_jwk_from_file (const char *filename)
-{
- json_t *jwk;
- json_error_t error;
-
- jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
-
- if (! jwk)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- ("Could not read OIDC RSA key from config file; %s\n"),
- error.text);
- }
-
- return jwk;
-}
-
-/**
- * @brief Write the JWK to file. If unsuccessful emit warning
- *
- * @param filename the name of the file the JWK is writen to
- * @param jwk the JWK that is going to be written
- * @return int Return GNUNET_OK if write is sucessfull
- */
-static int
-write_jwk_to_file (const char *filename,
- json_t *jwk)
-{
- if (json_dump_file (jwk, filename, JSON_INDENT (2)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- ("Could not write OIDC RSA key to file %s\n"),
- filename);
- return GNUNET_ERROR_TYPE_WARNING;
- }
- else
- return GNUNET_OK;
-}
-
-/**
- * @brief Generate a new RSA JSON Web Key
- *
- * @return json_t* the generated JWK
- */
-json_t *
-generate_jwk ()
-{
- json_t *jwk;
- jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
- jose_jwk_gen (NULL, jwk);
- json_incref (jwk);
- return jwk;
-}
-
-/**
* Responds to /jwks.json
*
* @param con_handle the connection handle
@@ -2574,30 +2618,10 @@ jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
char *oidc_jwk_path;
char *oidc_jwk_pub_str;
json_t *oidc_jwk;
- json_t *oidc_jwk_pub;
struct MHD_Response *resp;
struct RequestHandle *handle = cls;
- // Read OIDC directory from config
- if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
- "reclaim-rest-plugin",
- "oidc_dir",
- &oidc_directory))
- {
- // Could not read Config file
- handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_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;
- }
-
- // Create path to file
- // One extra byte for slash and one for \0
- oidc_jwk_path = malloc (strlen (oidc_directory) + strlen (
- OIDC_JWK_RSA_FILENAME) + 2);
- sprintf (oidc_jwk_path, "%s/%s", oidc_directory, OIDC_JWK_RSA_FILENAME);
-
+ oidc_jwk_path = get_oidc_jwk_path (cls);
oidc_jwk = read_jwk_from_file (oidc_jwk_path);
// Check if secret JWK exists
@@ -2620,14 +2644,12 @@ jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
}
// Convert secret JWK to public JWK
- oidc_jwk_pub = json_deep_copy (oidc_jwk);
- jose_jwk_pub (NULL, oidc_jwk_pub);
+ jose_jwk_pub (NULL, oidc_jwk);
// Encode JWK as string and return to API endpoint
- oidc_jwk_pub_str = json_dumps (oidc_jwk_pub, JSON_INDENT (1));
+ oidc_jwk_pub_str = json_dumps (oidc_jwk, JSON_INDENT (1));
resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- json_decref (oidc_jwk_pub);
json_decref (oidc_jwk);
GNUNET_free (oidc_jwk_pub_str);
free (oidc_jwk_pub_str);