diff options
author | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-19 22:16:00 +0200 |
---|---|---|
committer | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-19 22:16:00 +0200 |
commit | 0f75e5c54c6e6c9087cf565539266514abd67e98 (patch) | |
tree | a2e486faeb5c87f388b9eba39d59f7ad0fc5089b | |
parent | 6f626ca4add69247a5af436c6745491a1eb0fb6e (diff) | |
download | gnunet-0f75e5c54c6e6c9087cf565539266514abd67e98.tar.gz gnunet-0f75e5c54c6e6c9087cf565539266514abd67e98.zip |
change JWT algorithm to HMAC
-rw-r--r-- | src/identity-provider/identity-provider.conf | 1 | ||||
-rw-r--r-- | src/identity-provider/jwt.c | 49 | ||||
-rw-r--r-- | src/identity-provider/jwt.h | 3 | ||||
-rw-r--r-- | src/identity-provider/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 | |||
16 | #ADDRESS = https://identity.gnu:8000#/login | 16 | #ADDRESS = https://identity.gnu:8000#/login |
17 | ADDRESS = https://reclaim.ui/#/login | 17 | ADDRESS = https://reclaim.ui/#/login |
18 | PSW = secret | 18 | PSW = secret |
19 | JWT_SECRET = secret | ||
19 | EXPIRATION_TIME = 3600 | 20 | EXPIRATION_TIME = 3600 |
20 | 21 | ||
21 | [identity-provider-sqlite] | 22 | [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 @@ | |||
30 | 30 | ||
31 | #define JWT_ALG "alg" | 31 | #define JWT_ALG "alg" |
32 | 32 | ||
33 | /*TODO is this the correct way to define new algs? */ | 33 | /* Use 512bit HMAC */ |
34 | #define JWT_ALG_VALUE "urn:org:gnunet:jwt:alg:ecdsa:ed25519" | 34 | #define JWT_ALG_VALUE "HS512" |
35 | 35 | ||
36 | #define JWT_TYP "typ" | 36 | #define JWT_TYP "typ" |
37 | 37 | ||
38 | #define JWT_TYP_VALUE "jwt" | 38 | #define JWT_TYP_VALUE "jwt" |
39 | 39 | ||
40 | //TODO change server address | 40 | #define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo" |
41 | #define SERVER_ADDRESS "https://localhost" | ||
42 | 41 | ||
43 | static char* | 42 | static char* |
44 | create_jwt_header(void) | 43 | create_jwt_header(void) |
@@ -65,13 +64,12 @@ create_jwt_header(void) | |||
65 | */ | 64 | */ |
66 | char* | 65 | char* |
67 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | 66 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, |
67 | const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | ||
68 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | 68 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, |
69 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key) | 69 | const struct GNUNET_CRYPTO_AuthKey *priv_key) |
70 | { | 70 | { |
71 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | 71 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; |
72 | struct GNUNET_CRYPTO_EcdsaPublicKey sub_key; | 72 | struct GNUNET_HashCode signature; |
73 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
74 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
75 | char* audience; | 73 | char* audience; |
76 | char* subject; | 74 | char* subject; |
77 | char* header; | 75 | char* header; |
@@ -90,32 +88,25 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | |||
90 | //auth_time only if max_age | 88 | //auth_time only if max_age |
91 | //nonce only if nonce | 89 | //nonce only if nonce |
92 | // OPTIONAL acr,amr,azp | 90 | // OPTIONAL acr,amr,azp |
93 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &sub_key); | ||
94 | /* TODO maybe we should use a local identity here */ | ||
95 | subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, | 91 | subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, |
96 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 92 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); |
97 | audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, | 93 | audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, |
98 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | 94 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); |
99 | header = create_jwt_header (); | 95 | header = create_jwt_header (); |
100 | body = json_object (); | 96 | body = json_object (); |
101 | /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */ | 97 | |
102 | //iss REQUIRED case sensitive server uri with https | 98 | //iss REQUIRED case sensitive server uri with https |
99 | //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) | ||
103 | json_object_set_new (body, | 100 | json_object_set_new (body, |
104 | "iss", json_string (SERVER_ADDRESS)); | 101 | "iss", json_string (SERVER_ADDRESS)); |
105 | //sub REQUIRED public key identity, not exceed 255 ASCII length | 102 | //sub REQUIRED public key identity, not exceed 255 ASCII length |
106 | json_object_set_new (body, | 103 | json_object_set_new (body, |
107 | "sub", json_string (subject)); | 104 | "sub", json_string (subject)); |
108 | /* TODO what should be in here exactly? */ | ||
109 | //aud REQUIRED public key client_id must be there | 105 | //aud REQUIRED public key client_id must be there |
110 | json_object_set_new (body, | 106 | json_object_set_new (body, |
111 | "aud", json_string (audience)); | 107 | "aud", json_string (audience)); |
112 | for (le = attrs->list_head; NULL != le; le = le->next) | 108 | for (le = attrs->list_head; NULL != le; le = le->next) |
113 | { | 109 | { |
114 | /** | ||
115 | * TODO here we should have a function that | ||
116 | * calls the Attribute plugins to create a | ||
117 | * json representation for its value | ||
118 | */ | ||
119 | attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type, | 110 | attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type, |
120 | le->claim->data, | 111 | le->claim->data, |
121 | le->claim->data_size); | 112 | le->claim->data_size); |
@@ -148,32 +139,13 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | |||
148 | GNUNET_free (audience); | 139 | GNUNET_free (audience); |
149 | 140 | ||
150 | /** | 141 | /** |
151 | * TODO | ||
152 | * Creating the JWT signature. This might not be | 142 | * Creating the JWT signature. This might not be |
153 | * standards compliant, check. | 143 | * standards compliant, check. |
154 | */ | 144 | */ |
155 | GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); | 145 | GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); |
156 | 146 | GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature); | |
157 | purpose = | ||
158 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
159 | strlen (signature_target)); | ||
160 | purpose->size = | ||
161 | htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
162 | purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN); | ||
163 | GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target)); | ||
164 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, | ||
165 | purpose, | ||
166 | (struct GNUNET_CRYPTO_EcdsaSignature *)&signature)) | ||
167 | { | ||
168 | GNUNET_free (signature_target); | ||
169 | GNUNET_free (body_str); | ||
170 | GNUNET_free (body_base64); | ||
171 | GNUNET_free (header_base64); | ||
172 | GNUNET_free (purpose); | ||
173 | return NULL; | ||
174 | } | ||
175 | GNUNET_STRINGS_base64_encode ((const char*)&signature, | 147 | GNUNET_STRINGS_base64_encode ((const char*)&signature, |
176 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | 148 | sizeof (struct GNUNET_HashCode), |
177 | &signature_base64); | 149 | &signature_base64); |
178 | GNUNET_asprintf (&result, "%s.%s.%s", | 150 | GNUNET_asprintf (&result, "%s.%s.%s", |
179 | header_base64, body_base64, signature_base64); | 151 | header_base64, body_base64, signature_base64); |
@@ -184,6 +156,5 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | |||
184 | GNUNET_free (signature_base64); | 156 | GNUNET_free (signature_base64); |
185 | GNUNET_free (body_base64); | 157 | GNUNET_free (body_base64); |
186 | GNUNET_free (header_base64); | 158 | GNUNET_free (header_base64); |
187 | GNUNET_free (purpose); | ||
188 | return result; | 159 | return result; |
189 | } | 160 | } |
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 @@ | |||
3 | 3 | ||
4 | char* | 4 | char* |
5 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | 5 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, |
6 | const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | ||
6 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | 7 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, |
7 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key); | 8 | const struct GNUNET_CRYPTO_AuthKey *priv_key); |
8 | 9 | ||
9 | #endif | 10 | #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, | |||
1412 | json_t *root, *ticket_string, *nonce, *max_age; | 1412 | json_t *root, *ticket_string, *nonce, *max_age; |
1413 | json_error_t error; | 1413 | json_error_t error; |
1414 | char *json_response; | 1414 | char *json_response; |
1415 | char *jwt_secret; | ||
1415 | 1416 | ||
1416 | /* | 1417 | /* |
1417 | * Check Authorization | 1418 | * Check Authorization |
@@ -1447,7 +1448,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1447 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1448 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1448 | return; | 1449 | return; |
1449 | } | 1450 | } |
1450 | GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), &user_psw); | 1451 | GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); |
1451 | 1452 | ||
1452 | if ( NULL == user_psw ) | 1453 | if ( NULL == user_psw ) |
1453 | { | 1454 | { |
@@ -1598,7 +1599,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1598 | } | 1599 | } |
1599 | 1600 | ||
1600 | //decode code | 1601 | //decode code |
1601 | GNUNET_STRINGS_base64_decode(code,strlen(code),&code_output); | 1602 | GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); |
1602 | root = json_loads (code_output, 0, &error); | 1603 | root = json_loads (code_output, 0, &error); |
1603 | GNUNET_free(code_output); | 1604 | GNUNET_free(code_output); |
1604 | ticket_string = json_object_get (root, "ticket"); | 1605 | ticket_string = json_object_get (root, "ticket"); |
@@ -1717,15 +1718,32 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1717 | { | 1718 | { |
1718 | GNUNET_free_non_null(user_psw); | 1719 | GNUNET_free_non_null(user_psw); |
1719 | handle->emsg = GNUNET_strdup("invalid_request"); | 1720 | handle->emsg = GNUNET_strdup("invalid_request"); |
1720 | handle->edesc = GNUNET_strdup("invalid code...."); | 1721 | handle->edesc = GNUNET_strdup("invalid code..."); |
1721 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1722 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
1722 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1723 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1723 | GNUNET_free(ticket); | 1724 | GNUNET_free(ticket); |
1724 | return; | 1725 | return; |
1725 | } | 1726 | } |
1727 | if ( GNUNET_OK | ||
1728 | != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", | ||
1729 | "jwt_secret", &jwt_secret) ) | ||
1730 | { | ||
1731 | GNUNET_free_non_null(user_psw); | ||
1732 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1733 | handle->edesc = GNUNET_strdup("No signing secret configured!"); | ||
1734 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1735 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1736 | GNUNET_free(ticket); | ||
1737 | return; | ||
1738 | } | ||
1739 | struct GNUNET_CRYPTO_AuthKey jwt_sign_key; | ||
1740 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | ||
1741 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); | ||
1742 | GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key); | ||
1726 | char *id_token = jwt_create_from_list(&ticket->audience, | 1743 | char *id_token = jwt_create_from_list(&ticket->audience, |
1744 | &pk, | ||
1727 | cl, | 1745 | cl, |
1728 | GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego)); | 1746 | &jwt_sign_key); |
1729 | 1747 | ||
1730 | //Create random access_token | 1748 | //Create random access_token |
1731 | char* access_token_number; | 1749 | char* access_token_number; |