From 0f75e5c54c6e6c9087cf565539266514abd67e98 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Thu, 19 Jul 2018 22:16:00 +0200 Subject: [PATCH] change JWT algorithm to HMAC --- src/identity-provider/identity-provider.conf | 1 + src/identity-provider/jwt.c | 49 ++++--------------- src/identity-provider/jwt.h | 3 +- .../plugin_rest_openid_connect.c | 26 ++++++++-- 4 files changed, 35 insertions(+), 44 deletions(-) diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf index cc50152a1..99c0a50be 100644 --- a/src/identity-provider/identity-provider.conf +++ b/src/identity-provider/identity-provider.conf @@ -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] diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c index 1a984f7b5..7ac4f0025 100644 --- a/src/identity-provider/jwt.c +++ b/src/identity-provider/jwt.c @@ -30,15 +30,14 @@ #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; } diff --git a/src/identity-provider/jwt.h b/src/identity-provider/jwt.h index 072958973..80b6caa33 100644 --- a/src/identity-provider/jwt.h +++ b/src/identity-provider/jwt.h @@ -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 diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c index 9c2f7fb3d..cc4b83dae 100644 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ b/src/identity-provider/plugin_rest_openid_connect.c @@ -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; -- 2.25.1