gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] branch master updated (79eff4349 -> a87029a63)


From: gnunet
Subject: [gnunet] branch master updated (79eff4349 -> a87029a63)
Date: Thu, 09 Jun 2022 11:50:20 +0200

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a change to branch master
in repository gnunet.

    from 79eff4349 -fix duplicate naming of functions in messenger
     new 349b4e371 -init oidc RSA256 feature
     new a87029a63 RECLAIM: Improve OIDC plugin; now requires jose (new 
optional dependency)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 README                                   |   3 +-
 configure.ac                             |   5 +
 src/reclaim/Makefile.am                  |  10 +-
 src/reclaim/oidc_helper.c                | 160 +++++++++++++++----
 src/reclaim/oidc_helper.h                |  47 ++++--
 src/reclaim/plugin_rest_openid_connect.c | 256 ++++++++++++++++++++++++++++---
 src/reclaim/reclaim.conf                 |   4 +-
 7 files changed, 411 insertions(+), 74 deletions(-)

diff --git a/README b/README
index 9afd57043..7c4dfe8c0 100644
--- a/README
+++ b/README
@@ -147,7 +147,8 @@ Dependencies of optional components/functionality:
 - PABC credential support
   * libpabc            any            (for re:claimID zero-knowledge privacy
                                       credentials)
-
+- re:claimID OpenID Connect plugin
+  * libjose            any            (for re:claimID OpenID Connect support)
 
 
 Additional dependencies to run the GNUnet testsuite:
diff --git a/configure.ac b/configure.ac
index 733eea06e..c34e2a70e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -719,6 +719,11 @@ CHECK_WITH_LIB([jansson], [json_loads], [jansson.h], 
[HAVE_JANSSON])
 AS_IF([test "x$jansson" = "x0"],
   [AC_MSG_ERROR([GNUnet requires jansson])])
 
+# check for jose
+CHECK_WITH_LIB([jose], [jose_jwk_gen], [jose/jose.h], [HAVE_JOSE])
+AS_IF([test "x$jose" = "x0"],
+  [AC_MSG_WARN([reclaimID OpenID Connect plugin requires jose])])
+
 # check for libpulse (pulseaudio)
 CHECK_WITH_LIB([pulse], [pa_stream_peek], [pulse/simple.h], [HAVE_PULSE])
 
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
index a8300d6af..2f3df3456 100644
--- a/src/reclaim/Makefile.am
+++ b/src/reclaim/Makefile.am
@@ -10,9 +10,12 @@ endif
 
 
 REST_PLUGIN = \
-  libgnunet_plugin_rest_openid_connect.la \
   libgnunet_plugin_rest_reclaim.la
 
+if HAVE_JOSE
+REST_PLUGIN += libgnunet_plugin_rest_openid_connect.la
+endif
+
 CREDENTIAL_PLUGIN = \
   libgnunet_plugin_reclaim_credential_jwt.la
 
@@ -66,7 +69,7 @@ libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
   $(GN_PLUGIN_LDFLAGS)
 libgnunet_plugin_rest_reclaim_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
 
-
+if HAVE_JOSE
 libgnunet_plugin_rest_openid_connect_la_SOURCES = \
   plugin_rest_openid_connect.c \
   oidc_helper.h \
@@ -79,11 +82,12 @@ libgnunet_plugin_rest_openid_connect_la_LIBADD = \
   $(top_builddir)/src/gns/libgnunetgns.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson $(MHD_LIBS) \
+  $(LTLIBINTL) -ljansson -ljose $(MHD_LIBS) \
        $(LIBGCRYPT_LIBS)
 libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
   $(GN_PLUGIN_LDFLAGS)
 libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
+endif
 
 if HAVE_PABC
 libgnunet_plugin_rest_pabc_la_SOURCES = \
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 9237902ce..cfa71b26c 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -22,10 +22,12 @@
  * @file reclaim/oidc_helper.c
  * @brief helper library for OIDC related functions
  * @author Martin Schanzenbach
+ * @author Tristan Schwieren
  */
 #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"
@@ -115,13 +117,13 @@ is_claim_in_address_scope (const char *claim)
 
 
 static char *
-create_jwt_header (void)
+create_jwt_hmac_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_ALG, json_string (JWT_ALG_VALUE_HMAC));
   json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
 
   json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
@@ -356,40 +358,22 @@ OIDC_generate_userinfo (const struct 
GNUNET_IDENTITY_PublicKey *sub_key,
 }
 
 
-/**
- * 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 presentations credential presentation list (may be empty)
- * @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_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key,
+generate_id_token_body (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 char *secret_key)
+                        const char *nonce)
 {
   struct GNUNET_HashCode signature;
   struct GNUNET_TIME_Absolute exp_time;
   struct GNUNET_TIME_Absolute time_now;
+  json_t *body;
   char *audience;
   char *subject;
-  char *header;
   char *body_str;
-  char *result;
-  char *header_base64;
-  char *body_base64;
-  char *signature_target;
-  char *signature_base64;
-  json_t *body;
 
   body = generate_userinfo_json (sub_key,
                                  attrs,
@@ -409,7 +393,6 @@ OIDC_generate_id_token (const struct 
GNUNET_IDENTITY_PublicKey *aud_key,
     GNUNET_STRINGS_data_to_string_alloc (aud_key,
                                          sizeof(struct
                                                 GNUNET_IDENTITY_PublicKey));
-  header = create_jwt_header ();
 
   // aud REQUIRED public key client_id must be there
   json_object_set_new (body, "aud", json_string (audience));
@@ -429,19 +412,132 @@ OIDC_generate_id_token (const struct 
GNUNET_IDENTITY_PublicKey *aud_key,
   if (NULL != nonce)
     json_object_set_new (body, "nonce", json_string (nonce));
 
-  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
-  json_decref (body);
+  // Error checking
+  body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
 
+  json_decref (body);
+  GNUNET_free (subject);
+  GNUNET_free (audience);
+
+  return body_str;
+}
+
+
+/**
+ * Create a JWT using RSA256 algorithm 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 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)
+{
+  json_t *jws;
+  char *body_str;
+  char *result;
+
+  // Generate the body of the JSON Web Signature
+  body_str = generate_id_token_body (aud_key,
+                                     sub_key,
+                                     attrs,
+                                     presentations,
+                                     expiration_time,
+                                     nonce);
+
+  if (! body_str)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Body for the JWS could not be generated\n");
+  }
+
+  // Creating the JSON Web Signature.
+  jws = json_pack ("{s:o}", "payload",
+                           jose_b64_enc (body_str, strlen (body_str)));
+
+  if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Signature generation failed\n");
+  }
+
+  // Encoding JSON as compact JSON Web Signature 
+  GNUNET_asprintf (&result, "%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")) );
+
+  json_decref(jws);
+  GNUNET_free(body_str);
+  return result;
+}
+
+/**
+ * Create a JWT using HMAC (HS256) 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 presentations credential presentation list (may be empty)
+ * @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_generate_id_token_hmac (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 char *secret_key)
+{
+  struct GNUNET_HashCode signature;
+  struct GNUNET_TIME_Absolute exp_time;
+  struct GNUNET_TIME_Absolute time_now;
+  char *header;
+  char *header_base64;
+  char *body_str;
+  char *body_base64;
+  char *signature_target;
+  char *signature_base64;
+  char *result;
+
+  // Generate and encode Header
+  header = create_jwt_hmac_header ();
   GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
   fix_base64 (header_base64);
 
+  // Generate and encode the body of the JSON Web Signature
+  body_str = generate_id_token_body (aud_key,
+                                     sub_key,
+                                     attrs,
+                                     presentations,
+                                     expiration_time,
+                                     nonce);
+
+  if (! body_str)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Body for the JWS could not be generated\n");
+  }
+
   GNUNET_STRINGS_base64url_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.
@@ -463,12 +559,12 @@ OIDC_generate_id_token (const struct 
GNUNET_IDENTITY_PublicKey *aud_key,
                    body_base64,
                    signature_base64);
 
-  GNUNET_free (signature_target);
   GNUNET_free (header);
+  GNUNET_free (header_base64);
   GNUNET_free (body_str);
-  GNUNET_free (signature_base64);
   GNUNET_free (body_base64);
-  GNUNET_free (header_base64);
+  GNUNET_free (signature_target);
+  GNUNET_free (signature_base64);
   return result;
 }
 
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 2a8b7bbae..ea106b4f2 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -28,14 +28,12 @@
 #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 JWT_ALG_VALUE_HMAC "HS512"
+#define JWT_ALG_VALUE_RSA "RS256"
+
 #define SERVER_ADDRESS "https://api.reclaim";
 
 enum OIDC_VerificationOptions
@@ -52,7 +50,28 @@ enum OIDC_VerificationOptions
 };
 
 /**
- * Create a JWT from attributes
+ * Create a JWT using RSA256 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 presentations credential presentation list (may be empty)
+ * @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_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 using HMAC (HS256) from attributes
  *
  * @param aud_key the public of the audience
  * @param sub_key the public key of the subject
@@ -63,14 +82,14 @@ enum OIDC_VerificationOptions
  * @return a new base64-encoded JWT string.
  */
 char*
-OIDC_generate_id_token (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 char *secret_key);
+OIDC_generate_id_token_hmac (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 char *secret_key);
 
 /**
  * Builds an OIDC authorization code including
diff --git a/src/reclaim/plugin_rest_openid_connect.c 
b/src/reclaim/plugin_rest_openid_connect.c
index 1c00abcbd..bb8e1cd1e 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -20,6 +20,7 @@
 /**
  * @author Martin Schanzenbach
  * @author Philippe Buschmann
+ * @author Tristan Schwieren
  * @file identity/plugin_rest_openid_connect.c
  * @brief GNUnet Namestore REST plugin
  *
@@ -27,6 +28,7 @@
 #include "platform.h"
 #include <inttypes.h>
 #include <jansson.h>
+#include <jose/jose.h>
 
 #include "gnunet_buffer_lib.h"
 #include "gnunet_strings_lib.h"
@@ -62,6 +64,11 @@
  */
 #define GNUNET_REST_API_NS_TOKEN "/openid/token"
 
+/**
+ * JSON Web Keys endpoint
+ */
+#define GNUNET_REST_API_JWKS "/jwks.json"
+
 /**
  * UserInfo endpoint
  */
@@ -227,6 +234,11 @@
  */
 #define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
 
+/**
+ * OIDC key store file name
+ */
+#define OIDC_JWK_RSA_FILENAME "jwk_rsa.json"
+
 /**
  * How long to wait for a consume in userinfo endpoint
  */
@@ -302,6 +314,11 @@ struct Plugin
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 };
 
+/**
+ * @brief The RSA key used by the oidc enpoint
+ */
+json_t *oidc_jwk;
+
 /**
  * OIDC needed variables
  */
@@ -858,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
  */
@@ -1954,7 +2068,7 @@ check_authorization (struct RequestHandle *handle,
   // check client password
   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
                                                           
"reclaim-rest-plugin",
-                                                          "OIDC_CLIENT_SECRET",
+                                                          
"OIDC_CLIENT_HMAC_SECRET",
                                                           &expected_pass))
   {
     if (0 != strcmp (expected_pass, received_cpw))
@@ -2047,9 +2161,12 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   char *json_response;
   char *id_token;
   char *access_token;
+  char *jwa;
   char *jwt_secret;
   char *nonce = NULL;
   char *code_verifier;
+  json_t *oidc_jwk;
+  char *oidc_jwk_path;
 
   /*
    * Check Authorization
@@ -2156,32 +2273,66 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
     return;
   }
 
-
-  // TODO OPTIONAL acr,amr,azp
+  // Check if HMAC or RSA should be used
   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
                                                           
"reclaim-rest-plugin",
-                                                          "jwt_secret",
-                                                          &jwt_secret))
+                                                          
"oidc_json_web_algorithm",
+                                                          &jwa))
   {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
-    handle->edesc = GNUNET_strdup ("No signing secret configured!");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_free (code);
-    GNUNET_RECLAIM_attribute_list_destroy (cl);
-    GNUNET_RECLAIM_presentation_list_destroy (pl);
-    if (NULL != nonce)
-      GNUNET_free (nonce);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Could not read OIDC JSON Web Algorithm config attribute."
+                "Defaulting to RS256.");
+    jwa = JWT_ALG_VALUE_RSA;
+  }
+
+  if (strcmp(jwa, JWT_ALG_VALUE_RSA))
+  {
+    // Replace for now
+    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);
+  }
+  else if (strcmp(jwa, JWT_ALG_VALUE_HMAC))
+  {
+    // TODO OPTIONAL acr,amr,azp
+    if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                            
"reclaim-rest-plugin",
+                                                            "jwt_secret",
+                                                            &jwt_secret))
+    {
+      handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
+      handle->edesc = GNUNET_strdup ("No signing secret configured!");
+      handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+      GNUNET_free (code);
+      GNUNET_RECLAIM_attribute_list_destroy (cl);
+      GNUNET_RECLAIM_presentation_list_destroy (pl);
+      if (NULL != nonce)
+        GNUNET_free (nonce);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+
+    id_token = OIDC_generate_id_token_hmac (&ticket.audience,
+                                            &ticket.identity,
+                                            cl,
+                                            pl,
+                                            &expiration_time,
+                                            (NULL != nonce) ? nonce : NULL,
+                                            jwt_secret);
+
+    GNUNET_free (jwt_secret);
+  }
+  else 
+  {
+    // TODO: OPTION NOT FOUND ERROR
   }
-  id_token = OIDC_generate_id_token (&ticket.audience,
-                                     &ticket.identity,
-                                     cl,
-                                     pl,
-                                     &expiration_time,
-                                     (NULL != nonce) ? nonce : NULL,
-                                     jwt_secret);
-  GNUNET_free (jwt_secret);
+
   if (NULL != nonce)
     GNUNET_free (nonce);
   access_token = OIDC_access_token_new (&ticket);
@@ -2474,6 +2625,59 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   GNUNET_free (authorization);
 }
 
+/**
+ * Responds to /jwks.json
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+               const char *url,
+               void *cls)
+{
+  char *oidc_directory;
+  char *oidc_jwk_path;
+  char *oidc_jwk_pub_str;
+  json_t *oidc_jwk;
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  oidc_jwk_path = get_oidc_jwk_path (cls);
+  oidc_jwk = read_jwk_from_file (oidc_jwk_path);
+
+  // Check if secret JWK exists
+  if (! oidc_jwk)
+  {
+    // Generate and save a new key
+    oidc_jwk = generate_jwk ();
+
+    // Create new oidc directory
+    if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  ("Failed to create directory `%s' for storing oidc data\n"),
+                  oidc_directory);
+    }
+    else
+    {
+      write_jwk_to_file (oidc_jwk_path, oidc_jwk);
+    }
+  }
+
+  // Convert secret JWK to public JWK
+  jose_jwk_pub (NULL, oidc_jwk);
+
+  // Encode JWK as string and return to API endpoint
+  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);
+  GNUNET_free (oidc_jwk_pub_str);
+  free (oidc_jwk_pub_str);
+  cleanup_handle (handle);
+}
 
 /**
  * If listing is enabled, prints information about the egos.
@@ -2621,9 +2825,14 @@ oidc_config_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   sig_algs = json_array ();
   json_array_append_new (sig_algs,
                          json_string ("HS512"));
+  json_array_append_new (sig_algs,
+                         json_string ("RS256"));
   json_object_set_new (oidc_config,
                        "id_token_signing_alg_values_supported",
                        sig_algs);
+  json_object_set_new (oidc_config,
+                       "jwks_uri",
+                       json_string ("http://localhost:7776/jwks.json";));
   json_object_set_new (oidc_config,
                        "userinfo_endpoint",
                        json_string ("http://localhost:7776/openid/userinfo";));
@@ -2719,6 +2928,7 @@ rest_identity_process_request (struct 
GNUNET_REST_RequestHandle *rest_handle,
     { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
     { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
     { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
     { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
       &oidc_config_endpoint },
     { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf
index 8655f2e0b..c685042db 100644
--- a/src/reclaim/reclaim.conf
+++ b/src/reclaim/reclaim.conf
@@ -14,6 +14,8 @@ TICKET_REFRESH_INTERVAL = 6h
 [reclaim-rest-plugin]
 #ADDRESS = https://identity.gnu:8000#/login
 ADDRESS = https://ui.reclaim/#/login
-OIDC_CLIENT_SECRET = secret
+OIDC_JSON_WEB_ALGORITHM = RS256
+OIDC_CLIENT_HMAC_SECRET = secret
+OIDC_DIR = $GNUNET_DATA_HOME/oidc
 JWT_SECRET = secret
 EXPIRATION_TIME = 1d

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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