diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-06-22 20:14:04 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-06-22 20:14:04 +0200 |
commit | 84303b044db07e351e99c0338260ecea23012ec6 (patch) | |
tree | f5718cab374a8bf86c5f7b904f6bd45215f46536 | |
parent | a022af20e654100b99db1a9205bea43f9271526b (diff) | |
download | gnunet-84303b044db07e351e99c0338260ecea23012ec6.tar.gz gnunet-84303b044db07e351e99c0338260ecea23012ec6.zip |
RECLAIM: Improve OIDC userinfo caching; add config option for timeout
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 59 | ||||
-rw-r--r-- | src/reclaim/reclaim.conf | 1 |
2 files changed, 47 insertions, 13 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 0ffe1b6c8..769ce553f 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -307,6 +307,11 @@ static struct GNUNET_GNS_Handle *gns_handle; | |||
307 | static struct GNUNET_RECLAIM_Handle *idp; | 307 | static struct GNUNET_RECLAIM_Handle *idp; |
308 | 308 | ||
309 | /** | 309 | /** |
310 | * Timeout for consume call on userinfo | ||
311 | */ | ||
312 | static struct GNUNET_TIME_Relative consume_timeout; | ||
313 | |||
314 | /** | ||
310 | * @brief struct returned by the initialization function of the plugin | 315 | * @brief struct returned by the initialization function of the plugin |
311 | */ | 316 | */ |
312 | struct Plugin | 317 | struct Plugin |
@@ -976,8 +981,8 @@ get_oidc_jwk_path (void *cls) | |||
976 | { | 981 | { |
977 | char *oidc_directory; | 982 | char *oidc_directory; |
978 | char *oidc_jwk_path; | 983 | char *oidc_jwk_path; |
979 | 984 | ||
980 | oidc_directory = get_oidc_dir_path(cls); | 985 | oidc_directory = get_oidc_dir_path (cls); |
981 | 986 | ||
982 | // Create path to file | 987 | // Create path to file |
983 | GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory, | 988 | GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory, |
@@ -2183,6 +2188,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2183 | json_t *oidc_jwk; | 2188 | json_t *oidc_jwk; |
2184 | char *oidc_jwk_path; | 2189 | char *oidc_jwk_path; |
2185 | char *oidc_directory; | 2190 | char *oidc_directory; |
2191 | char *tmp_at; | ||
2186 | 2192 | ||
2187 | /* | 2193 | /* |
2188 | * Check Authorization | 2194 | * Check Authorization |
@@ -2312,7 +2318,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2312 | { | 2318 | { |
2313 | // Generate and save a new key | 2319 | // Generate and save a new key |
2314 | oidc_jwk = generate_jwk (); | 2320 | oidc_jwk = generate_jwk (); |
2315 | oidc_directory = get_oidc_dir_path(cls); | 2321 | oidc_directory = get_oidc_dir_path (cls); |
2316 | 2322 | ||
2317 | // Create new oidc directory | 2323 | // Create new oidc directory |
2318 | if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory)) | 2324 | if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory)) |
@@ -2374,14 +2380,25 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2374 | if (NULL != nonce) | 2380 | if (NULL != nonce) |
2375 | GNUNET_free (nonce); | 2381 | GNUNET_free (nonce); |
2376 | access_token = OIDC_access_token_new (&ticket); | 2382 | access_token = OIDC_access_token_new (&ticket); |
2377 | /* Store mapping from access token to code so we can later | 2383 | /** |
2378 | * fall back on the provided attributes in userinfo | 2384 | * Store mapping from access token to code so we can later |
2385 | * fall back on the provided attributes in userinfo one time. | ||
2379 | */ | 2386 | */ |
2380 | GNUNET_CRYPTO_hash (access_token, | 2387 | GNUNET_CRYPTO_hash (access_token, |
2381 | strlen (access_token), | 2388 | strlen (access_token), |
2382 | &cache_key); | 2389 | &cache_key); |
2383 | char *tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache, | 2390 | /** |
2384 | &cache_key); | 2391 | * Note to future self: This cache has the following purpose: |
2392 | * Some OIDC plugins call the userendpoint right after receiving an | ||
2393 | * ID token and access token. There are reasons why this would make sense. | ||
2394 | * Others not so much. | ||
2395 | * In any case, in order to smoothen out the user experience upon login | ||
2396 | * (authorization), we speculatively cache the next | ||
2397 | * userinfo response in case the actual resolution through reclaim/GNS | ||
2398 | * takes too long. | ||
2399 | */ | ||
2400 | tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache, | ||
2401 | &cache_key); | ||
2385 | GNUNET_CONTAINER_multihashmap_put (oidc_code_cache, | 2402 | GNUNET_CONTAINER_multihashmap_put (oidc_code_cache, |
2386 | &cache_key, | 2403 | &cache_key, |
2387 | code, | 2404 | code, |
@@ -2490,15 +2507,18 @@ consume_ticket (void *cls, | |||
2490 | 2507 | ||
2491 | 2508 | ||
2492 | static void | 2509 | static void |
2493 | consume_timeout (void*cls) | 2510 | consume_fail (void *cls) |
2494 | { | 2511 | { |
2495 | struct RequestHandle *handle = cls; | 2512 | struct RequestHandle *handle = cls; |
2496 | struct GNUNET_HashCode cache_key; | 2513 | struct GNUNET_HashCode cache_key; |
2497 | struct GNUNET_RECLAIM_AttributeList *cl = NULL; | 2514 | struct GNUNET_RECLAIM_AttributeList *cl = NULL; |
2498 | struct GNUNET_RECLAIM_PresentationList *pl = NULL; | 2515 | struct GNUNET_RECLAIM_PresentationList *pl = NULL; |
2499 | struct GNUNET_RECLAIM_Ticket ticket; | 2516 | struct GNUNET_RECLAIM_Ticket ticket; |
2517 | struct MHD_Response *resp; | ||
2500 | char *nonce; | 2518 | char *nonce; |
2501 | char *cached_code; | 2519 | char *cached_code; |
2520 | char *result_str; | ||
2521 | |||
2502 | 2522 | ||
2503 | handle->consume_timeout_op = NULL; | 2523 | handle->consume_timeout_op = NULL; |
2504 | if (NULL != handle->idp_op) | 2524 | if (NULL != handle->idp_op) |
@@ -2520,6 +2540,12 @@ consume_timeout (void*cls) | |||
2520 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | 2540 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); |
2521 | return; | 2541 | return; |
2522 | } | 2542 | } |
2543 | /** | ||
2544 | * Remove the cached item | ||
2545 | */ | ||
2546 | GNUNET_CONTAINER_multihashmap_remove (oidc_code_cache, | ||
2547 | &cache_key, | ||
2548 | cached_code); | ||
2523 | 2549 | ||
2524 | // decode code | 2550 | // decode code |
2525 | if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience, | 2551 | if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience, |
@@ -2537,8 +2563,7 @@ consume_timeout (void*cls) | |||
2537 | return; | 2563 | return; |
2538 | } | 2564 | } |
2539 | 2565 | ||
2540 | struct MHD_Response *resp; | 2566 | GNUNET_free (cached_code); |
2541 | char *result_str; | ||
2542 | 2567 | ||
2543 | result_str = OIDC_generate_userinfo (&handle->ticket.identity, | 2568 | result_str = OIDC_generate_userinfo (&handle->ticket.identity, |
2544 | cl, | 2569 | cl, |
@@ -2652,8 +2677,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2652 | 2677 | ||
2653 | /* If the consume takes too long, we use values from the cache */ | 2678 | /* If the consume takes too long, we use values from the cache */ |
2654 | handle->access_token = GNUNET_strdup (authorization_access_token); | 2679 | handle->access_token = GNUNET_strdup (authorization_access_token); |
2655 | handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (CONSUME_TIMEOUT, | 2680 | handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (consume_timeout, |
2656 | &consume_timeout, | 2681 | &consume_fail, |
2657 | handle); | 2682 | handle); |
2658 | handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp, | 2683 | handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp, |
2659 | privkey, | 2684 | privkey, |
@@ -2690,7 +2715,7 @@ jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2690 | { | 2715 | { |
2691 | // Generate and save a new key | 2716 | // Generate and save a new key |
2692 | oidc_jwk = generate_jwk (); | 2717 | oidc_jwk = generate_jwk (); |
2693 | oidc_directory = get_oidc_dir_path(cls); | 2718 | oidc_directory = get_oidc_dir_path (cls); |
2694 | 2719 | ||
2695 | // Create new oidc directory | 2720 | // Create new oidc directory |
2696 | if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory)) | 2721 | if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory)) |
@@ -3028,6 +3053,14 @@ libgnunet_plugin_rest_openid_connect_init (void *cls) | |||
3028 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); | 3053 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); |
3029 | gns_handle = GNUNET_GNS_connect (cfg); | 3054 | gns_handle = GNUNET_GNS_connect (cfg); |
3030 | idp = GNUNET_RECLAIM_connect (cfg); | 3055 | idp = GNUNET_RECLAIM_connect (cfg); |
3056 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
3057 | "reclaim-rest-plugin", | ||
3058 | "OIDC_USERINFO_CONSUME_TIMEOUT", | ||
3059 | &consume_timeout)) | ||
3060 | { | ||
3061 | consume_timeout = CONSUME_TIMEOUT; | ||
3062 | } | ||
3063 | |||
3031 | 3064 | ||
3032 | state = ID_REST_STATE_INIT; | 3065 | state = ID_REST_STATE_INIT; |
3033 | GNUNET_asprintf (&allow_methods, | 3066 | GNUNET_asprintf (&allow_methods, |
diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf index c685042db..07facc232 100644 --- a/src/reclaim/reclaim.conf +++ b/src/reclaim/reclaim.conf | |||
@@ -17,5 +17,6 @@ ADDRESS = https://ui.reclaim/#/login | |||
17 | OIDC_JSON_WEB_ALGORITHM = RS256 | 17 | OIDC_JSON_WEB_ALGORITHM = RS256 |
18 | OIDC_CLIENT_HMAC_SECRET = secret | 18 | OIDC_CLIENT_HMAC_SECRET = secret |
19 | OIDC_DIR = $GNUNET_DATA_HOME/oidc | 19 | OIDC_DIR = $GNUNET_DATA_HOME/oidc |
20 | OIDC_USERINFO_CONSUME_TIMEOUT = 5s | ||
20 | JWT_SECRET = secret | 21 | JWT_SECRET = secret |
21 | EXPIRATION_TIME = 1d | 22 | EXPIRATION_TIME = 1d |