aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2020-12-08 16:50:27 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2020-12-08 16:50:27 +0900
commit7ce054864a112f459a75ab542f844a8be0e6c47c (patch)
tree3b57538de1365180f540bf704d2909714a90d0c3
parent61f7bf618b336c4d9349067ececdd7e5f051d67c (diff)
downloadgnunet-7ce054864a112f459a75ab542f844a8be0e6c47c.tar.gz
gnunet-7ce054864a112f459a75ab542f844a8be0e6c47c.zip
RECLAIM: Return userinfo claims from cache
-rw-r--r--src/reclaim/oidc_helper.c78
-rw-r--r--src/reclaim/oidc_helper.h38
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c151
3 files changed, 217 insertions, 50 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index c6d56e02d..1dde7b673 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -567,6 +567,48 @@ OIDC_build_authz_code (const struct GNUNET_IDENTITY_PrivateKey *issuer,
567} 567}
568 568
569 569
570enum GNUNET_GenericReturnValue
571check_code_challenge (const char *code_challenge,
572 uint32_t code_challenge_len,
573 const char *code_verifier)
574{
575 char *code_verifier_hash;
576 char *expected_code_challenge;
577
578 if (0 == code_challenge_len) /* Only check if this code requires a CV */
579 return GNUNET_OK;
580 if (NULL == code_verifier)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Expected code verifier!\n");
584 return GNUNET_SYSERR;
585 }
586 code_verifier_hash = GNUNET_malloc (256 / 8);
587 // hash code verifier
588 gcry_md_hash_buffer (GCRY_MD_SHA256,
589 code_verifier_hash,
590 code_verifier,
591 strlen (code_verifier));
592 // encode code verifier
593 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
594 &expected_code_challenge);
595 GNUNET_free (code_verifier_hash);
596 if (0 !=
597 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
598 {
599 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
600 "Invalid code verifier! Expected: %s, Got: %.*s\n",
601 expected_code_challenge,
602 code_challenge_len,
603 code_challenge);
604 GNUNET_free (expected_code_challenge);
605 return GNUNET_SYSERR;
606 }
607 GNUNET_free (expected_code_challenge);
608 return GNUNET_OK;
609}
610
611
570/** 612/**
571 * Parse reclaim ticket and nonce from 613 * Parse reclaim ticket and nonce from
572 * authorization code. 614 * authorization code.
@@ -589,16 +631,15 @@ OIDC_parse_authz_code (const struct GNUNET_IDENTITY_PublicKey *audience,
589 struct GNUNET_RECLAIM_Ticket *ticket, 631 struct GNUNET_RECLAIM_Ticket *ticket,
590 struct GNUNET_RECLAIM_AttributeList **attrs, 632 struct GNUNET_RECLAIM_AttributeList **attrs,
591 struct GNUNET_RECLAIM_PresentationList **presentations, 633 struct GNUNET_RECLAIM_PresentationList **presentations,
592 char **nonce_str) 634 char **nonce_str,
635 enum OIDC_VerificationOptions opts)
593{ 636{
594 char *code_payload; 637 char *code_payload;
595 char *ptr; 638 char *ptr;
596 char *plaintext; 639 char *plaintext;
597 char *attrs_ser; 640 char *attrs_ser;
598 char *presentations_ser; 641 char *presentations_ser;
599 char *expected_code_challenge;
600 char *code_challenge; 642 char *code_challenge;
601 char *code_verifier_hash;
602 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 643 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
603 struct GNUNET_IDENTITY_Signature *signature; 644 struct GNUNET_IDENTITY_Signature *signature;
604 uint32_t code_challenge_len; 645 uint32_t code_challenge_len;
@@ -636,38 +677,15 @@ OIDC_parse_authz_code (const struct GNUNET_IDENTITY_PublicKey *audience,
636 // cmp code_challenge code_verifier 677 // cmp code_challenge code_verifier
637 code_challenge_len = ntohl (params->code_challenge_len); 678 code_challenge_len = ntohl (params->code_challenge_len);
638 code_challenge = ((char *) &params[1]); 679 code_challenge = ((char *) &params[1]);
639 if (0 != code_challenge_len) /* Only check if this code requires a CV */ 680 if (!(opts & OIDC_VERIFICATION_NO_CODE_VERIFIER))
640 { 681 {
641 if (NULL == code_verifier) 682 if (GNUNET_OK != check_code_challenge (code_challenge,
642 { 683 code_challenge_len,
643 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 684 code_verifier))
644 "Expected code verifier!\n");
645 GNUNET_free (code_payload);
646 return GNUNET_SYSERR;
647 }
648 code_verifier_hash = GNUNET_malloc (256 / 8);
649 // hash code verifier
650 gcry_md_hash_buffer (GCRY_MD_SHA256,
651 code_verifier_hash,
652 code_verifier,
653 strlen (code_verifier));
654 // encode code verifier
655 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
656 &expected_code_challenge);
657 GNUNET_free (code_verifier_hash);
658 if (0 !=
659 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
660 { 685 {
661 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
662 "Invalid code verifier! Expected: %s, Got: %.*s\n",
663 expected_code_challenge,
664 code_challenge_len,
665 code_challenge);
666 GNUNET_free (code_payload); 686 GNUNET_free (code_payload);
667 GNUNET_free (expected_code_challenge);
668 return GNUNET_SYSERR; 687 return GNUNET_SYSERR;
669 } 688 }
670 GNUNET_free (expected_code_challenge);
671 } 689 }
672 nonce_len = ntohl (params->nonce_len); 690 nonce_len = ntohl (params->nonce_len);
673 if (0 != nonce_len) 691 if (0 != nonce_len)
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index eb1022423..2a8b7bbae 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -38,6 +38,19 @@
38 38
39#define SERVER_ADDRESS "https://api.reclaim" 39#define SERVER_ADDRESS "https://api.reclaim"
40 40
41enum OIDC_VerificationOptions
42{
43 /**
44 * Strict verification
45 */
46 OIDC_VERIFICATION_DEFAULT = 0,
47
48 /**
49 * Do not check code verifier even if expected
50 */
51 OIDC_VERIFICATION_NO_CODE_VERIFIER = 1
52};
53
41/** 54/**
42 * Create a JWT from attributes 55 * Create a JWT from attributes
43 * 56 *
@@ -51,12 +64,13 @@
51 */ 64 */
52char* 65char*
53OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key, 66OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key,
54 const struct GNUNET_IDENTITY_PublicKey *sub_key, 67 const struct GNUNET_IDENTITY_PublicKey *sub_key,
55 const struct GNUNET_RECLAIM_AttributeList *attrs, 68 const struct GNUNET_RECLAIM_AttributeList *attrs,
56 const struct GNUNET_RECLAIM_PresentationList *presentations, 69 const struct
57 const struct GNUNET_TIME_Relative *expiration_time, 70 GNUNET_RECLAIM_PresentationList *presentations,
58 const char *nonce, 71 const struct GNUNET_TIME_Relative *expiration_time,
59 const char *secret_key); 72 const char *nonce,
73 const char *secret_key);
60 74
61/** 75/**
62 * Builds an OIDC authorization code including 76 * Builds an OIDC authorization code including
@@ -68,13 +82,15 @@ OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key,
68 * @param presentations credential presentation list 82 * @param presentations credential presentation list
69 * @param nonce the nonce to include in the code 83 * @param nonce the nonce to include in the code
70 * @param code_challenge PKCE code challenge 84 * @param code_challenge PKCE code challenge
85 * @param opts verification options
71 * @return a new authorization code (caller must free) 86 * @return a new authorization code (caller must free)
72 */ 87 */
73char* 88char*
74OIDC_build_authz_code (const struct GNUNET_IDENTITY_PrivateKey *issuer, 89OIDC_build_authz_code (const struct GNUNET_IDENTITY_PrivateKey *issuer,
75 const struct GNUNET_RECLAIM_Ticket *ticket, 90 const struct GNUNET_RECLAIM_Ticket *ticket,
76 const struct GNUNET_RECLAIM_AttributeList *attrs, 91 const struct GNUNET_RECLAIM_AttributeList *attrs,
77 const struct GNUNET_RECLAIM_PresentationList *presentations, 92 const struct
93 GNUNET_RECLAIM_PresentationList *presentations,
78 const char *nonce, 94 const char *nonce,
79 const char *code_challenge); 95 const char *code_challenge);
80 96
@@ -99,7 +115,8 @@ OIDC_parse_authz_code (const struct GNUNET_IDENTITY_PublicKey *ecdsa_pub,
99 struct GNUNET_RECLAIM_Ticket *ticket, 115 struct GNUNET_RECLAIM_Ticket *ticket,
100 struct GNUNET_RECLAIM_AttributeList **attrs, 116 struct GNUNET_RECLAIM_AttributeList **attrs,
101 struct GNUNET_RECLAIM_PresentationList **presentations, 117 struct GNUNET_RECLAIM_PresentationList **presentations,
102 char **nonce); 118 char **nonce,
119 enum OIDC_VerificationOptions opts);
103 120
104/** 121/**
105 * Build a token response for a token request 122 * Build a token response for a token request
@@ -126,7 +143,7 @@ OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket);
126 * Parse an access token 143 * Parse an access token
127 */ 144 */
128int 145int
129OIDC_access_token_parse (const char* token, 146OIDC_access_token_parse (const char*token,
130 struct GNUNET_RECLAIM_Ticket **ticket); 147 struct GNUNET_RECLAIM_Ticket **ticket);
131 148
132 149
@@ -154,6 +171,7 @@ OIDC_check_scopes_for_claim_request (const char *scopes,
154char * 171char *
155OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key, 172OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key,
156 const struct GNUNET_RECLAIM_AttributeList *attrs, 173 const struct GNUNET_RECLAIM_AttributeList *attrs,
157 const struct GNUNET_RECLAIM_PresentationList *presentations); 174 const struct
175 GNUNET_RECLAIM_PresentationList *presentations);
158 176
159#endif 177#endif
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 7a8a886bd..8d21a5c99 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -227,6 +227,11 @@
227 */ 227 */
228#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied" 228#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
229 229
230/**
231 * How long to wait for a consume in userinfo endpoint
232 */
233#define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
234 GNUNET_TIME_UNIT_SECONDS,2)
230 235
231/** 236/**
232 * OIDC ignored parameter array 237 * OIDC ignored parameter array
@@ -240,7 +245,12 @@ static char *OIDC_ignored_parameter_array[] = { "display",
240 "acr_values" }; 245 "acr_values" };
241 246
242/** 247/**
243 * OIDC Hash map that keeps track of issued cookies 248 * OIDC hashmap for cached access tokens and codes
249 */
250struct GNUNET_CONTAINER_MultiHashMap *oidc_code_cache;
251
252/**
253 * OIDC hashmap that keeps track of issued cookies
244 */ 254 */
245struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map; 255struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map;
246 256
@@ -460,6 +470,11 @@ struct RequestHandle
460 struct GNUNET_RECLAIM_Operation *idp_op; 470 struct GNUNET_RECLAIM_Operation *idp_op;
461 471
462 /** 472 /**
473 * Timeout task for consume
474 */
475 struct GNUNET_SCHEDULER_Task *consume_timeout_op;
476
477 /**
463 * Attribute iterator 478 * Attribute iterator
464 */ 479 */
465 struct GNUNET_RECLAIM_AttributeIterator *attr_it; 480 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
@@ -506,6 +521,11 @@ struct RequestHandle
506 char *url; 521 char *url;
507 522
508 /** 523 /**
524 * The passed access token
525 */
526 char *access_token;
527
528 /**
509 * The tld for redirect 529 * The tld for redirect
510 */ 530 */
511 char *tld; 531 char *tld;
@@ -571,6 +591,8 @@ cleanup_handle (struct RequestHandle *handle)
571 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); 591 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
572 if (NULL != handle->idp_op) 592 if (NULL != handle->idp_op)
573 GNUNET_RECLAIM_cancel (handle->idp_op); 593 GNUNET_RECLAIM_cancel (handle->idp_op);
594 if (NULL != handle->consume_timeout_op)
595 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
574 GNUNET_free (handle->url); 596 GNUNET_free (handle->url);
575 GNUNET_free (handle->tld); 597 GNUNET_free (handle->tld);
576 GNUNET_free (handle->redirect_prefix); 598 GNUNET_free (handle->redirect_prefix);
@@ -601,6 +623,8 @@ cleanup_handle (struct RequestHandle *handle)
601 GNUNET_CONTAINER_DLL_remove (requests_head, 623 GNUNET_CONTAINER_DLL_remove (requests_head,
602 requests_tail, 624 requests_tail,
603 handle); 625 handle);
626 if (NULL != handle->access_token)
627 GNUNET_free (handle->access_token);
604 GNUNET_free (handle); 628 GNUNET_free (handle);
605} 629}
606 630
@@ -1282,8 +1306,8 @@ code_redirect (void *cls)
1282 { 1306 {
1283 if (GNUNET_OK != 1307 if (GNUNET_OK !=
1284 GNUNET_IDENTITY_public_key_from_string (handle->oidc 1308 GNUNET_IDENTITY_public_key_from_string (handle->oidc
1285 ->login_identity, 1309 ->login_identity,
1286 &pubkey)) 1310 &pubkey))
1287 { 1311 {
1288 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE); 1312 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE);
1289 handle->edesc = 1313 handle->edesc =
@@ -1662,7 +1686,7 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1662 1686
1663 if (GNUNET_OK != 1687 if (GNUNET_OK !=
1664 GNUNET_IDENTITY_public_key_from_string (handle->oidc->client_id, 1688 GNUNET_IDENTITY_public_key_from_string (handle->oidc->client_id,
1665 &handle->oidc->client_pkey)) 1689 &handle->oidc->client_pkey))
1666 { 1690 {
1667 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT); 1691 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT);
1668 handle->edesc = GNUNET_strdup ("The client is not authorized to request an " 1692 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
@@ -2071,7 +2095,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2071 2095
2072 // decode code 2096 // decode code
2073 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket, 2097 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2074 &cl, &pl, &nonce)) 2098 &cl, &pl, &nonce,
2099 OIDC_VERIFICATION_DEFAULT))
2075 { 2100 {
2076 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); 2101 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2077 handle->edesc = GNUNET_strdup ("invalid code"); 2102 handle->edesc = GNUNET_strdup ("invalid code");
@@ -2080,7 +2105,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2080 GNUNET_SCHEDULER_add_now (&do_error, handle); 2105 GNUNET_SCHEDULER_add_now (&do_error, handle);
2081 return; 2106 return;
2082 } 2107 }
2083 GNUNET_free (code);
2084 2108
2085 // create jwt 2109 // create jwt
2086 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, 2110 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -2091,6 +2115,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2091 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR); 2115 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
2092 handle->edesc = GNUNET_strdup ("gnunet configuration failed"); 2116 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2093 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 2117 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2118 GNUNET_free (code);
2094 GNUNET_SCHEDULER_add_now (&do_error, handle); 2119 GNUNET_SCHEDULER_add_now (&do_error, handle);
2095 return; 2120 return;
2096 } 2121 }
@@ -2105,6 +2130,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2105 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); 2130 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2106 handle->edesc = GNUNET_strdup ("No signing secret configured!"); 2131 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2107 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 2132 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2133 GNUNET_free (code);
2108 GNUNET_SCHEDULER_add_now (&do_error, handle); 2134 GNUNET_SCHEDULER_add_now (&do_error, handle);
2109 return; 2135 return;
2110 } 2136 }
@@ -2116,6 +2142,26 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2116 (NULL != nonce) ? nonce : NULL, 2142 (NULL != nonce) ? nonce : NULL,
2117 jwt_secret); 2143 jwt_secret);
2118 access_token = OIDC_access_token_new (&ticket); 2144 access_token = OIDC_access_token_new (&ticket);
2145 /* Store mapping from access token to code so we can later
2146 * fall back on the provided attributes in userinfo
2147 */
2148 GNUNET_CRYPTO_hash (access_token,
2149 strlen (access_token),
2150 &cache_key);
2151 char *tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2152 &cache_key);
2153 GNUNET_CONTAINER_multihashmap_put (oidc_code_cache,
2154 &cache_key,
2155 code,
2156 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
2157 /* If there was a previus code in there, free the old value */
2158 if (NULL != tmp_at)
2159 {
2160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2161 "OIDC access token already issued. Cleanup.\n");
2162 GNUNET_free (tmp_at);
2163 }
2164
2119 OIDC_build_token_response (access_token, 2165 OIDC_build_token_response (access_token,
2120 id_token, 2166 id_token,
2121 &expiration_time, 2167 &expiration_time,
@@ -2149,6 +2195,10 @@ consume_ticket (void *cls,
2149 struct GNUNET_RECLAIM_PresentationListEntry *atle; 2195 struct GNUNET_RECLAIM_PresentationListEntry *atle;
2150 struct MHD_Response *resp; 2196 struct MHD_Response *resp;
2151 char *result_str; 2197 char *result_str;
2198
2199 if (NULL != handle->consume_timeout_op)
2200 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2201 handle->consume_timeout_op = NULL;
2152 handle->idp_op = NULL; 2202 handle->idp_op = NULL;
2153 2203
2154 if (NULL == identity) 2204 if (NULL == identity)
@@ -2180,8 +2230,9 @@ consume_ticket (void *cls,
2180 for (atle = handle->presentations->list_head; 2230 for (atle = handle->presentations->list_head;
2181 NULL != atle; atle = atle->next) 2231 NULL != atle; atle = atle->next)
2182 { 2232 {
2183 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->presentation->credential_id, 2233 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (
2184 &pres->credential_id)) 2234 &atle->presentation->credential_id,
2235 &pres->credential_id))
2185 continue; 2236 continue;
2186 break; /** already in list **/ 2237 break; /** already in list **/
2187 } 2238 }
@@ -2190,8 +2241,8 @@ consume_ticket (void *cls,
2190 /** Credential matches for attribute, add **/ 2241 /** Credential matches for attribute, add **/
2191 atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); 2242 atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
2192 atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type, 2243 atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type,
2193 pres->data, 2244 pres->data,
2194 pres->data_size); 2245 pres->data_size);
2195 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head, 2246 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2196 handle->presentations->list_tail, 2247 handle->presentations->list_tail,
2197 atle); 2248 atle);
@@ -2199,6 +2250,69 @@ consume_ticket (void *cls,
2199} 2250}
2200 2251
2201 2252
2253static void
2254consume_timeout (void*cls)
2255{
2256 struct RequestHandle *handle = cls;
2257 struct GNUNET_HashCode cache_key;
2258 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2259 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2260 struct GNUNET_RECLAIM_Ticket ticket;
2261 char *nonce;
2262 char *cached_code;
2263
2264 handle->consume_timeout_op = NULL;
2265 if (NULL != handle->idp_op)
2266 GNUNET_RECLAIM_cancel (handle->idp_op);
2267 handle->idp_op = NULL;
2268
2269 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2270 "Ticket consumptioned timed out. Using cache...\n");
2271 GNUNET_CRYPTO_hash (handle->access_token,
2272 strlen (handle->access_token),
2273 &cache_key);
2274 cached_code = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2275 &cache_key);
2276 if (NULL == cached_code)
2277 {
2278 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2279 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2280 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2281 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2282 return;
2283 }
2284
2285 // decode code
2286 if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2287 cached_code, NULL, &ticket,
2288 &cl, &pl, &nonce,
2289 OIDC_VERIFICATION_NO_CODE_VERIFIER))
2290 {
2291 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2292 handle->edesc = GNUNET_strdup ("invalid code");
2293 handle->response_code = MHD_HTTP_BAD_REQUEST;
2294 GNUNET_free (cached_code);
2295 GNUNET_SCHEDULER_add_now (&do_error, handle);
2296 return;
2297 }
2298
2299 struct MHD_Response *resp;
2300 char *result_str;
2301
2302 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2303 cl,
2304 pl);
2305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2306 resp = GNUNET_REST_create_response (result_str);
2307 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2308 GNUNET_free (result_str);
2309 GNUNET_free (nonce);
2310 GNUNET_RECLAIM_attribute_list_destroy (cl);
2311 GNUNET_RECLAIM_presentation_list_destroy (pl);
2312 cleanup_handle (handle);
2313}
2314
2315
2202/** 2316/**
2203 * Responds to userinfo GET and url-encoded POST request 2317 * Responds to userinfo GET and url-encoded POST request
2204 * 2318 *
@@ -2295,6 +2409,11 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2295 handle->presentations = 2409 handle->presentations =
2296 GNUNET_new (struct GNUNET_RECLAIM_PresentationList); 2410 GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
2297 2411
2412 /* If the consume takes too long, we use values from the cache */
2413 handle->access_token = GNUNET_strdup (authorization_access_token);
2414 handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (CONSUME_TIMEOUT,
2415 &consume_timeout,
2416 handle);
2298 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp, 2417 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2299 privkey, 2418 privkey,
2300 &handle->ticket, 2419 &handle->ticket,
@@ -2554,6 +2673,10 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
2554 if (NULL == OIDC_cookie_jar_map) 2673 if (NULL == OIDC_cookie_jar_map)
2555 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, 2674 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2556 GNUNET_NO); 2675 GNUNET_NO);
2676 if (NULL == oidc_code_cache)
2677 oidc_code_cache = GNUNET_CONTAINER_multihashmap_create (10,
2678 GNUNET_NO);
2679
2557 handle->response_code = 0; 2680 handle->response_code = 0;
2558 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 2681 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
2559 handle->proc_cls = proc_cls; 2682 handle->proc_cls = proc_cls;
@@ -2646,6 +2769,14 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
2646 NULL); 2769 NULL);
2647 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map); 2770 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2648 } 2771 }
2772 if (NULL != oidc_code_cache)
2773 {
2774 GNUNET_CONTAINER_multihashmap_iterate (oidc_code_cache,
2775 &cleanup_hashmap,
2776 NULL);
2777 GNUNET_CONTAINER_multihashmap_destroy (oidc_code_cache);
2778 }
2779
2649 GNUNET_free (allow_methods); 2780 GNUNET_free (allow_methods);
2650 if (NULL != gns_handle) 2781 if (NULL != gns_handle)
2651 GNUNET_GNS_disconnect (gns_handle); 2782 GNUNET_GNS_disconnect (gns_handle);