aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/plugin_rest_openid_connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/plugin_rest_openid_connect.c')
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c823
1 files changed, 467 insertions, 356 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 36ae937c1..06e1b0061 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -28,6 +28,8 @@
28#include <inttypes.h> 28#include <inttypes.h>
29#include <jansson.h> 29#include <jansson.h>
30 30
31#include "gnunet_buffer_lib.h"
32#include "gnunet_strings_lib.h"
31#include "gnunet_gns_service.h" 33#include "gnunet_gns_service.h"
32#include "gnunet_gnsrecord_lib.h" 34#include "gnunet_gnsrecord_lib.h"
33#include "gnunet_identity_service.h" 35#include "gnunet_identity_service.h"
@@ -39,12 +41,18 @@
39#include "gnunet_signatures.h" 41#include "gnunet_signatures.h"
40#include "microhttpd.h" 42#include "microhttpd.h"
41#include "oidc_helper.h" 43#include "oidc_helper.h"
44
42/** 45/**
43 * REST root namespace 46 * REST root namespace
44 */ 47 */
45#define GNUNET_REST_API_NS_OIDC "/openid" 48#define GNUNET_REST_API_NS_OIDC "/openid"
46 49
47/** 50/**
51 * OIDC config
52 */
53#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
54
55/**
48 * Authorize endpoint 56 * Authorize endpoint
49 */ 57 */
50#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" 58#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
@@ -237,12 +245,6 @@ static char *OIDC_ignored_parameter_array[] = { "display",
237struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map; 245struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map;
238 246
239/** 247/**
240 * Hash map that links the issued access token to the corresponding ticket and
241 * ego
242 */
243struct GNUNET_CONTAINER_MultiHashMap *OIDC_access_token_map;
244
245/**
246 * The configuration handle 248 * The configuration handle
247 */ 249 */
248const struct GNUNET_CONFIGURATION_Handle *cfg; 250const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -253,6 +255,36 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
253static char *allow_methods; 255static char *allow_methods;
254 256
255/** 257/**
258 * Ego list
259 */
260static struct EgoEntry *ego_head;
261
262/**
263 * Ego list
264 */
265static struct EgoEntry *ego_tail;
266
267/**
268 * The processing state
269 */
270static int state;
271
272/**
273 * Handle to Identity service.
274 */
275static struct GNUNET_IDENTITY_Handle *identity_handle;
276
277/**
278 * GNS handle
279 */
280static struct GNUNET_GNS_Handle *gns_handle;
281
282/**
283 * Identity Provider
284 */
285static struct GNUNET_RECLAIM_Handle *idp;
286
287/**
256 * @brief struct returned by the initialization function of the plugin 288 * @brief struct returned by the initialization function of the plugin
257 */ 289 */
258struct Plugin 290struct Plugin
@@ -325,10 +357,6 @@ struct OIDC_Variables
325 */ 357 */
326 char *code_verifier; 358 char *code_verifier;
327 359
328 /**
329 * The response JSON
330 */
331 json_t *response;
332}; 360};
333 361
334/** 362/**
@@ -365,15 +393,6 @@ struct EgoEntry
365 393
366struct RequestHandle 394struct RequestHandle
367{ 395{
368 /**
369 * Ego list
370 */
371 struct EgoEntry *ego_head;
372
373 /**
374 * Ego list
375 */
376 struct EgoEntry *ego_tail;
377 396
378 /** 397 /**
379 * Selected ego 398 * Selected ego
@@ -391,39 +410,14 @@ struct RequestHandle
391 struct OIDC_Variables *oidc; 410 struct OIDC_Variables *oidc;
392 411
393 /** 412 /**
394 * The processing state
395 */
396 int state;
397
398 /**
399 * Handle to Identity service.
400 */
401 struct GNUNET_IDENTITY_Handle *identity_handle;
402
403 /**
404 * Rest connection
405 */
406 struct GNUNET_REST_RequestHandle *rest_handle;
407
408 /**
409 * GNS handle
410 */
411 struct GNUNET_GNS_Handle *gns_handle;
412
413 /**
414 * GNS lookup op 413 * GNS lookup op
415 */ 414 */
416 struct GNUNET_GNS_LookupRequest *gns_op; 415 struct GNUNET_GNS_LookupRequest *gns_op;
417 416
418 /** 417 /**
419 * Handle to NAMESTORE 418 * Rest connection
420 */
421 struct GNUNET_NAMESTORE_Handle *namestore_handle;
422
423 /**
424 * Iterator for NAMESTORE
425 */ 419 */
426 struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; 420 struct GNUNET_REST_RequestHandle *rest_handle;
427 421
428 /** 422 /**
429 * Attribute claim list for id_token 423 * Attribute claim list for id_token
@@ -446,10 +440,6 @@ struct RequestHandle
446 */ 440 */
447 struct GNUNET_IDENTITY_Operation *op; 441 struct GNUNET_IDENTITY_Operation *op;
448 442
449 /**
450 * Identity Provider
451 */
452 struct GNUNET_RECLAIM_Handle *idp;
453 443
454 /** 444 /**
455 * Idp Operation 445 * Idp Operation
@@ -531,8 +521,14 @@ struct RequestHandle
531 * Reponse code 521 * Reponse code
532 */ 522 */
533 int response_code; 523 int response_code;
524
525 /**
526 * Public client
527 */
528 int public_client;
534}; 529};
535 530
531
536/** 532/**
537 * Cleanup lookup handle 533 * Cleanup lookup handle
538 * @param handle Handle to clean up 534 * @param handle Handle to clean up
@@ -540,13 +536,10 @@ struct RequestHandle
540static void 536static void
541cleanup_handle (struct RequestHandle *handle) 537cleanup_handle (struct RequestHandle *handle)
542{ 538{
543 struct EgoEntry *ego_entry;
544 539
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); 540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
546 if (NULL != handle->timeout_task) 541 if (NULL != handle->timeout_task)
547 GNUNET_SCHEDULER_cancel (handle->timeout_task); 542 GNUNET_SCHEDULER_cancel (handle->timeout_task);
548 if (NULL != handle->identity_handle)
549 GNUNET_IDENTITY_disconnect (handle->identity_handle);
550 if (NULL != handle->attr_it) 543 if (NULL != handle->attr_it)
551 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); 544 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
552 if (NULL != handle->attest_it) 545 if (NULL != handle->attest_it)
@@ -555,8 +548,6 @@ cleanup_handle (struct RequestHandle *handle)
555 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); 548 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
556 if (NULL != handle->idp_op) 549 if (NULL != handle->idp_op)
557 GNUNET_RECLAIM_cancel (handle->idp_op); 550 GNUNET_RECLAIM_cancel (handle->idp_op);
558 if (NULL != handle->idp)
559 GNUNET_RECLAIM_disconnect (handle->idp);
560 GNUNET_free (handle->url); 551 GNUNET_free (handle->url);
561 GNUNET_free (handle->tld); 552 GNUNET_free (handle->tld);
562 GNUNET_free (handle->redirect_prefix); 553 GNUNET_free (handle->redirect_prefix);
@@ -565,11 +556,6 @@ cleanup_handle (struct RequestHandle *handle)
565 GNUNET_free (handle->edesc); 556 GNUNET_free (handle->edesc);
566 if (NULL != handle->gns_op) 557 if (NULL != handle->gns_op)
567 GNUNET_GNS_lookup_cancel (handle->gns_op); 558 GNUNET_GNS_lookup_cancel (handle->gns_op);
568 if (NULL != handle->gns_handle)
569 GNUNET_GNS_disconnect (handle->gns_handle);
570
571 if (NULL != handle->namestore_handle)
572 GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
573 if (NULL != handle->oidc) 559 if (NULL != handle->oidc)
574 { 560 {
575 GNUNET_free (handle->oidc->client_id); 561 GNUNET_free (handle->oidc->client_id);
@@ -579,7 +565,6 @@ cleanup_handle (struct RequestHandle *handle)
579 GNUNET_free (handle->oidc->response_type); 565 GNUNET_free (handle->oidc->response_type);
580 GNUNET_free (handle->oidc->scope); 566 GNUNET_free (handle->oidc->scope);
581 GNUNET_free (handle->oidc->state); 567 GNUNET_free (handle->oidc->state);
582 json_decref (handle->oidc->response);
583 GNUNET_free (handle->oidc); 568 GNUNET_free (handle->oidc);
584 } 569 }
585 if (NULL!=handle->attr_idtoken_list) 570 if (NULL!=handle->attr_idtoken_list)
@@ -589,15 +574,6 @@ cleanup_handle (struct RequestHandle *handle)
589 if (NULL!=handle->attests_list) 574 if (NULL!=handle->attests_list)
590 GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); 575 GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list);
591 576
592 while (NULL != (ego_entry = handle->ego_head))
593 {
594 GNUNET_CONTAINER_DLL_remove (handle->ego_head,
595 handle->ego_tail,
596 ego_entry);
597 GNUNET_free (ego_entry->identifier);
598 GNUNET_free (ego_entry->keystring);
599 GNUNET_free (ego_entry);
600 }
601 GNUNET_free (handle); 577 GNUNET_free (handle);
602} 578}
603 579
@@ -655,6 +631,8 @@ do_userinfo_error (void *cls)
655 struct MHD_Response *resp; 631 struct MHD_Response *resp;
656 char *error; 632 char *error;
657 633
634 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
635 "Error: %s\n", handle->edesc);
658 GNUNET_asprintf (&error, 636 GNUNET_asprintf (&error,
659 "error=\"%s\", error_description=\"%s\"", 637 "error=\"%s\", error_description=\"%s\"",
660 handle->emsg, 638 handle->emsg,
@@ -710,27 +688,6 @@ do_timeout (void *cls)
710 688
711 689
712/** 690/**
713 * Return attributes for claim
714 *
715 * @param cls the request handle
716 */
717static void
718return_userinfo_response (void *cls)
719{
720 char *result_str;
721 struct RequestHandle *handle = cls;
722 struct MHD_Response *resp;
723
724 result_str = json_dumps (handle->oidc->response, 0);
725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str);
726 resp = GNUNET_REST_create_response (result_str);
727 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
728 GNUNET_free (result_str);
729 cleanup_handle (handle);
730}
731
732
733/**
734 * Respond to OPTIONS request 691 * Respond to OPTIONS request
735 * 692 *
736 * @param con_handle the connection handle 693 * @param con_handle the connection handle
@@ -854,7 +811,9 @@ login_redirect (void *cls)
854{ 811{
855 char *login_base_url; 812 char *login_base_url;
856 char *new_redirect; 813 char *new_redirect;
814 char *tmp;
857 struct MHD_Response *resp; 815 struct MHD_Response *resp;
816 struct GNUNET_Buffer buf = { 0 };
858 struct RequestHandle *handle = cls; 817 struct RequestHandle *handle = cls;
859 818
860 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, 819 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -862,27 +821,68 @@ login_redirect (void *cls)
862 "address", 821 "address",
863 &login_base_url)) 822 &login_base_url))
864 { 823 {
865 GNUNET_asprintf (&new_redirect, 824 GNUNET_buffer_write_str (&buf, login_base_url);
866 "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", 825 GNUNET_buffer_write_fstr (&buf,
867 login_base_url, 826 "?%s=%s",
868 OIDC_RESPONSE_TYPE_KEY, 827 OIDC_RESPONSE_TYPE_KEY,
869 handle->oidc->response_type, 828 handle->oidc->response_type);
870 OIDC_CLIENT_ID_KEY, 829 GNUNET_buffer_write_fstr (&buf,
871 handle->oidc->client_id, 830 "&%s=%s",
872 OIDC_REDIRECT_URI_KEY, 831 OIDC_CLIENT_ID_KEY,
873 handle->oidc->redirect_uri, 832 handle->oidc->client_id);
874 OIDC_SCOPE_KEY, 833 GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
875 handle->oidc->scope, 834 strlen (handle->oidc->redirect_uri),
876 OIDC_STATE_KEY, 835 &tmp);
877 (NULL != handle->oidc->state) ? handle->oidc->state : "", 836 GNUNET_buffer_write_fstr (&buf,
878 OIDC_CODE_CHALLENGE_KEY, 837 "&%s=%s",
879 (NULL != handle->oidc->code_challenge) ? 838 OIDC_REDIRECT_URI_KEY,
880 handle->oidc->code_challenge : "", 839 tmp);
881 OIDC_NONCE_KEY, 840 GNUNET_free (tmp);
882 (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", 841 GNUNET_STRINGS_urlencode (handle->oidc->scope,
883 OIDC_CLAIMS_KEY, 842 strlen (handle->oidc->scope),
884 (NULL != handle->oidc->claims) ? handle->oidc->claims : 843 &tmp);
885 ""); 844 GNUNET_buffer_write_fstr (&buf,
845 "&%s=%s",
846 OIDC_SCOPE_KEY,
847 tmp);
848 GNUNET_free (tmp);
849 if (NULL != handle->oidc->state)
850 {
851 GNUNET_STRINGS_urlencode (handle->oidc->state,
852 strlen (handle->oidc->state),
853 &tmp);
854 GNUNET_buffer_write_fstr (&buf,
855 "&%s=%s",
856 OIDC_STATE_KEY,
857 handle->oidc->state);
858 GNUNET_free (tmp);
859 }
860 if (NULL != handle->oidc->code_challenge)
861 {
862 GNUNET_buffer_write_fstr (&buf,
863 "&%s=%s",
864 OIDC_CODE_CHALLENGE_KEY,
865 handle->oidc->code_challenge);
866 }
867 if (NULL != handle->oidc->nonce)
868 {
869 GNUNET_buffer_write_fstr (&buf,
870 "&%s=%s",
871 OIDC_NONCE_KEY,
872 handle->oidc->nonce);
873 }
874 if (NULL != handle->oidc->claims)
875 {
876 GNUNET_STRINGS_urlencode (handle->oidc->claims,
877 strlen (handle->oidc->claims),
878 &tmp);
879 GNUNET_buffer_write_fstr (&buf,
880 "&%s=%s",
881 OIDC_CLAIMS_KEY,
882 tmp);
883 GNUNET_free (tmp);
884 }
885 new_redirect = GNUNET_buffer_reap_str (&buf);
886 resp = GNUNET_REST_create_response (""); 886 resp = GNUNET_REST_create_response ("");
887 MHD_add_response_header (resp, "Location", new_redirect); 887 MHD_add_response_header (resp, "Location", new_redirect);
888 GNUNET_free (login_base_url); 888 GNUNET_free (login_base_url);
@@ -954,6 +954,8 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
954 handle->redirect_prefix, 954 handle->redirect_prefix,
955 handle->tld, 955 handle->tld,
956 handle->redirect_suffix, 956 handle->redirect_suffix,
957 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
958 "&"),
957 handle->oidc->response_type, 959 handle->oidc->response_type,
958 code_string, 960 code_string,
959 handle->oidc->state); 961 handle->oidc->state);
@@ -961,8 +963,10 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
961 else 963 else
962 { 964 {
963 GNUNET_asprintf (&redirect_uri, 965 GNUNET_asprintf (&redirect_uri,
964 "%s?%s=%s&state=%s", 966 "%s%s%s=%s&state=%s",
965 handle->oidc->redirect_uri, 967 handle->oidc->redirect_uri,
968 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
969 "&"),
966 handle->oidc->response_type, 970 handle->oidc->response_type,
967 code_string, 971 code_string,
968 handle->oidc->state); 972 handle->oidc->state);
@@ -1041,7 +1045,7 @@ oidc_attest_collect_finished_cb (void *cls)
1041 handle->attest_it = NULL; 1045 handle->attest_it = NULL;
1042 merged_list = attribute_list_merge (handle->attr_idtoken_list, 1046 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1043 handle->attr_userinfo_list); 1047 handle->attr_userinfo_list);
1044 handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, 1048 handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1045 &handle->priv_key, 1049 &handle->priv_key,
1046 &handle->oidc->client_pkey, 1050 &handle->oidc->client_pkey,
1047 merged_list, 1051 merged_list,
@@ -1108,7 +1112,7 @@ oidc_attr_collect_finished_cb (void *cls)
1108 } 1112 }
1109 handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); 1113 handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
1110 handle->attest_it = 1114 handle->attest_it =
1111 GNUNET_RECLAIM_get_attestations_start (handle->idp, 1115 GNUNET_RECLAIM_get_attestations_start (idp,
1112 &handle->priv_key, 1116 &handle->priv_key,
1113 &oidc_iteration_error, 1117 &oidc_iteration_error,
1114 handle, 1118 handle,
@@ -1125,9 +1129,6 @@ attr_in_claims_request (struct RequestHandle *handle,
1125 const char *attr_name, 1129 const char *attr_name,
1126 const char *claims_parameter) 1130 const char *claims_parameter)
1127{ 1131{
1128 char *scope_variables;
1129 char *scope_variable;
1130 char delimiter[] = " ";
1131 int ret = GNUNET_NO; 1132 int ret = GNUNET_NO;
1132 json_t *root; 1133 json_t *root;
1133 json_error_t error; 1134 json_error_t error;
@@ -1135,19 +1136,12 @@ attr_in_claims_request (struct RequestHandle *handle,
1135 const char *key; 1136 const char *key;
1136 json_t *value; 1137 json_t *value;
1137 1138
1138 scope_variables = GNUNET_strdup (handle->oidc->scope); 1139 /** Check if attribute is requested through standard scope **/
1139 scope_variable = strtok (scope_variables, delimiter); 1140 if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope,
1140 while (NULL != scope_variable) 1141 attr_name))
1141 { 1142 return GNUNET_YES;
1142 if (0 == strcmp (attr_name, scope_variable))
1143 break;
1144 scope_variable = strtok (NULL, delimiter);
1145 }
1146 if (NULL != scope_variable)
1147 ret = GNUNET_YES;
1148 GNUNET_free (scope_variables);
1149 1143
1150 /** Try claims parameter if no in scope */ 1144 /** Try claims parameter if not in scope */
1151 if ((NULL != handle->oidc->claims) && 1145 if ((NULL != handle->oidc->claims) &&
1152 (GNUNET_YES != ret)) 1146 (GNUNET_YES != ret))
1153 { 1147 {
@@ -1274,7 +1268,7 @@ code_redirect (void *cls)
1274 return; 1268 return;
1275 } 1269 }
1276 // iterate over egos and compare their public key 1270 // iterate over egos and compare their public key
1277 for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry; 1271 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1278 handle->ego_entry = handle->ego_entry->next) 1272 handle->ego_entry = handle->ego_entry->next)
1279 { 1273 {
1280 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); 1274 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
@@ -1282,13 +1276,12 @@ code_redirect (void *cls)
1282 { 1276 {
1283 handle->priv_key = 1277 handle->priv_key =
1284 *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); 1278 *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1285 handle->idp = GNUNET_RECLAIM_connect (cfg);
1286 handle->attr_idtoken_list = 1279 handle->attr_idtoken_list =
1287 GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 1280 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1288 handle->attr_userinfo_list = 1281 handle->attr_userinfo_list =
1289 GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 1282 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1290 handle->attr_it = 1283 handle->attr_it =
1291 GNUNET_RECLAIM_get_attributes_start (handle->idp, 1284 GNUNET_RECLAIM_get_attributes_start (idp,
1292 &handle->priv_key, 1285 &handle->priv_key,
1293 &oidc_iteration_error, 1286 &oidc_iteration_error,
1294 handle, 1287 handle,
@@ -1433,7 +1426,7 @@ client_redirect (void *cls)
1433 1426
1434 /* Lookup client redirect uri to verify request */ 1427 /* Lookup client redirect uri to verify request */
1435 handle->gns_op = 1428 handle->gns_op =
1436 GNUNET_GNS_lookup (handle->gns_handle, 1429 GNUNET_GNS_lookup (gns_handle,
1437 GNUNET_GNS_EMPTY_LABEL_AT, 1430 GNUNET_GNS_EMPTY_LABEL_AT,
1438 &handle->oidc->client_pkey, 1431 &handle->oidc->client_pkey,
1439 GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, 1432 GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
@@ -1448,6 +1441,7 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1448{ 1441{
1449 struct GNUNET_HashCode hc; 1442 struct GNUNET_HashCode hc;
1450 char *value; 1443 char *value;
1444 char *res;
1451 1445
1452 GNUNET_CRYPTO_hash (key, strlen (key), &hc); 1446 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1453 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle 1447 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
@@ -1458,7 +1452,8 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1458 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc); 1452 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1459 if (NULL == value) 1453 if (NULL == value)
1460 return NULL; 1454 return NULL;
1461 return GNUNET_strdup (value); 1455 GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1456 return res;
1462} 1457}
1463 1458
1464 1459
@@ -1657,14 +1652,14 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1657 1652
1658 // If we know this identity, translated the corresponding TLD 1653 // If we know this identity, translated the corresponding TLD
1659 // TODO: We might want to have a reverse lookup functionality for TLDs? 1654 // TODO: We might want to have a reverse lookup functionality for TLDs?
1660 for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) 1655 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1661 { 1656 {
1662 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); 1657 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1663 GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey); 1658 GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey);
1664 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey)) 1659 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1665 { 1660 {
1666 handle->tld = GNUNET_strdup (tmp_ego->identifier); 1661 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1667 handle->ego_entry = handle->ego_tail; 1662 handle->ego_entry = ego_tail;
1668 } 1663 }
1669 } 1664 }
1670 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY); 1665 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
@@ -1749,16 +1744,16 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1749 1744
1750 1745
1751static int 1746static int
1752check_authorization (struct RequestHandle *handle, 1747parse_credentials_basic_auth (struct RequestHandle *handle,
1753 struct GNUNET_CRYPTO_EcdsaPublicKey *cid) 1748 char **client_id,
1749 char **client_secret)
1754{ 1750{
1755 struct GNUNET_HashCode cache_key; 1751 struct GNUNET_HashCode cache_key;
1756 char *authorization; 1752 char *authorization;
1757 char *credentials; 1753 char *credentials;
1758 char *basic_authorization; 1754 char *basic_authorization;
1759 char *client_id; 1755 char *client_id_tmp;
1760 char *pass; 1756 char *pass;
1761 char *expected_pass;
1762 1757
1763 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, 1758 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
1764 strlen (OIDC_AUTHORIZATION_HEADER_KEY), 1759 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
@@ -1766,12 +1761,7 @@ check_authorization (struct RequestHandle *handle,
1766 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle 1761 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1767 ->header_param_map, 1762 ->header_param_map,
1768 &cache_key)) 1763 &cache_key))
1769 {
1770 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1771 handle->edesc = GNUNET_strdup ("missing authorization");
1772 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1773 return GNUNET_SYSERR; 1764 return GNUNET_SYSERR;
1774 }
1775 authorization = 1765 authorization =
1776 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map, 1766 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1777 &cache_key); 1767 &cache_key);
@@ -1779,44 +1769,117 @@ check_authorization (struct RequestHandle *handle,
1779 // split header in "Basic" and [content] 1769 // split header in "Basic" and [content]
1780 credentials = strtok (authorization, " "); 1770 credentials = strtok (authorization, " ");
1781 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials))) 1771 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1782 {
1783 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1784 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1785 return GNUNET_SYSERR; 1772 return GNUNET_SYSERR;
1786 }
1787 credentials = strtok (NULL, " "); 1773 credentials = strtok (NULL, " ");
1788 if (NULL == credentials) 1774 if (NULL == credentials)
1789 {
1790 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1791 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1792 return GNUNET_SYSERR; 1775 return GNUNET_SYSERR;
1793 }
1794 GNUNET_STRINGS_base64_decode (credentials, 1776 GNUNET_STRINGS_base64_decode (credentials,
1795 strlen (credentials), 1777 strlen (credentials),
1796 (void **) &basic_authorization); 1778 (void **) &basic_authorization);
1797 1779
1798 if (NULL == basic_authorization) 1780 if (NULL == basic_authorization)
1799 {
1800 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1801 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1802 return GNUNET_SYSERR; 1781 return GNUNET_SYSERR;
1803 } 1782 client_id_tmp = strtok (basic_authorization, ":");
1804 client_id = strtok (basic_authorization, ":"); 1783 if (NULL == client_id_tmp)
1805 if (NULL == client_id)
1806 { 1784 {
1807 GNUNET_free (basic_authorization); 1785 GNUNET_free (basic_authorization);
1808 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1809 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1810 return GNUNET_SYSERR; 1786 return GNUNET_SYSERR;
1811 } 1787 }
1812 pass = strtok (NULL, ":"); 1788 pass = strtok (NULL, ":");
1813 if (NULL == pass) 1789 if (NULL == pass)
1814 { 1790 {
1815 GNUNET_free (basic_authorization); 1791 GNUNET_free (basic_authorization);
1816 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1817 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1818 return GNUNET_SYSERR; 1792 return GNUNET_SYSERR;
1819 } 1793 }
1794 *client_id = strdup (client_id_tmp);
1795 *client_secret = strdup (pass);
1796 GNUNET_free (basic_authorization);
1797 return GNUNET_OK;
1798}
1799
1800
1801static int
1802parse_credentials_post_body (struct RequestHandle *handle,
1803 char **client_id,
1804 char **client_secret)
1805{
1806 struct GNUNET_HashCode cache_key;
1807 char *client_id_tmp;
1808 char *pass;
1809
1810 GNUNET_CRYPTO_hash ("client_id",
1811 strlen ("client_id"),
1812 &cache_key);
1813 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1814 ->url_param_map,
1815 &cache_key))
1816 return GNUNET_SYSERR;
1817 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1818 handle->rest_handle->url_param_map,
1819 &cache_key);
1820 if (NULL == client_id_tmp)
1821 return GNUNET_SYSERR;
1822 *client_id = strdup (client_id_tmp);
1823 GNUNET_CRYPTO_hash ("client_secret",
1824 strlen ("client_secret"),
1825 &cache_key);
1826 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
1827 ->url_param_map,
1828 &cache_key))
1829 return GNUNET_SYSERR;
1830 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1831 &cache_key);
1832 if (NULL == pass)
1833 return GNUNET_SYSERR;
1834 *client_secret = strdup (pass);
1835 return GNUNET_OK;
1836}
1837
1838
1839static int
1840check_authorization (struct RequestHandle *handle,
1841 struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
1842{
1843 char *expected_pass;
1844 char *received_cid;
1845 char *received_cpw;
1846 char *pkce_cv;
1847
1848 if (GNUNET_OK == parse_credentials_basic_auth (handle,
1849 &received_cid,
1850 &received_cpw))
1851 {
1852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1853 "Received client credentials in HTTP AuthZ header\n");
1854 }
1855 else if (GNUNET_OK == parse_credentials_post_body (handle,
1856 &received_cid,
1857 &received_cpw))
1858 {
1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1860 "Received client credentials in POST body\n");
1861 }
1862 else
1863 {
1864 /** Allow public clients with PKCE **/
1865 pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1866 if (NULL == pkce_cv)
1867 {
1868 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1869 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1870 return GNUNET_SYSERR;
1871 }
1872 handle->public_client = GNUNET_YES;
1873 GNUNET_free (pkce_cv);
1874 received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1875 GNUNET_STRINGS_string_to_data (received_cid,
1876 strlen (received_cid),
1877 cid,
1878 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1879 GNUNET_free (received_cid);
1880 return GNUNET_OK;
1881
1882 }
1820 1883
1821 // check client password 1884 // check client password
1822 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, 1885 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -1824,9 +1887,8 @@ check_authorization (struct RequestHandle *handle,
1824 "OIDC_CLIENT_SECRET", 1887 "OIDC_CLIENT_SECRET",
1825 &expected_pass)) 1888 &expected_pass))
1826 { 1889 {
1827 if (0 != strcmp (expected_pass, pass)) 1890 if (0 != strcmp (expected_pass, received_cpw))
1828 { 1891 {
1829 GNUNET_free (basic_authorization);
1830 GNUNET_free (expected_pass); 1892 GNUNET_free (expected_pass);
1831 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); 1893 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1832 handle->response_code = MHD_HTTP_UNAUTHORIZED; 1894 handle->response_code = MHD_HTTP_UNAUTHORIZED;
@@ -1836,33 +1898,33 @@ check_authorization (struct RequestHandle *handle,
1836 } 1898 }
1837 else 1899 else
1838 { 1900 {
1839 GNUNET_free (basic_authorization);
1840 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR); 1901 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
1841 handle->edesc = GNUNET_strdup ("gnunet configuration failed"); 1902 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1842 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 1903 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1843 return GNUNET_SYSERR; 1904 return GNUNET_SYSERR;
1844 } 1905 }
1845
1846 // check client_id 1906 // check client_id
1847 for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry; 1907 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1848 handle->ego_entry = handle->ego_entry->next) 1908 handle->ego_entry = handle->ego_entry->next)
1849 { 1909 {
1850 if (0 == strcmp (handle->ego_entry->keystring, client_id)) 1910 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1851 break; 1911 break;
1852 } 1912 }
1853 if (NULL == handle->ego_entry) 1913 if (NULL == handle->ego_entry)
1854 { 1914 {
1855 GNUNET_free (basic_authorization); 1915 GNUNET_free (received_cpw);
1916 GNUNET_free (received_cid);
1856 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); 1917 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
1857 handle->response_code = MHD_HTTP_UNAUTHORIZED; 1918 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1858 return GNUNET_SYSERR; 1919 return GNUNET_SYSERR;
1859 } 1920 }
1860 GNUNET_STRINGS_string_to_data (client_id, 1921 GNUNET_STRINGS_string_to_data (received_cid,
1861 strlen (client_id), 1922 strlen (received_cid),
1862 cid, 1923 cid,
1863 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); 1924 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1864 1925
1865 GNUNET_free (basic_authorization); 1926 GNUNET_free (received_cpw);
1927 GNUNET_free (received_cid);
1866 return GNUNET_OK; 1928 return GNUNET_OK;
1867} 1929}
1868 1930
@@ -1874,7 +1936,7 @@ find_ego (struct RequestHandle *handle,
1874 struct EgoEntry *ego_entry; 1936 struct EgoEntry *ego_entry;
1875 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 1937 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
1876 1938
1877 for (ego_entry = handle->ego_head; NULL != ego_entry; 1939 for (ego_entry = ego_head; NULL != ego_entry;
1878 ego_entry = ego_entry->next) 1940 ego_entry = ego_entry->next)
1879 { 1941 {
1880 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); 1942 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
@@ -1885,26 +1947,6 @@ find_ego (struct RequestHandle *handle,
1885} 1947}
1886 1948
1887 1949
1888static void
1889persist_access_token (const struct RequestHandle *handle,
1890 const char *access_token,
1891 const struct GNUNET_RECLAIM_Ticket *ticket)
1892{
1893 struct GNUNET_HashCode hc;
1894 struct GNUNET_RECLAIM_Ticket *ticketbuf;
1895
1896 GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc);
1897 ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
1898 *ticketbuf = *ticket;
1899 GNUNET_assert (GNUNET_SYSERR !=
1900 GNUNET_CONTAINER_multihashmap_put (
1901 OIDC_access_token_map,
1902 &hc,
1903 ticketbuf,
1904 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1905}
1906
1907
1908/** 1950/**
1909 * Responds to token url-encoded POST request 1951 * Responds to token url-encoded POST request
1910 * 1952 *
@@ -2008,7 +2050,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2008 } 2050 }
2009 2051
2010 // decode code 2052 // decode code
2011 if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket, 2053 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2012 &cl, &al, &nonce)) 2054 &cl, &al, &nonce))
2013 { 2055 {
2014 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); 2056 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
@@ -2046,20 +2088,19 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2046 GNUNET_SCHEDULER_add_now (&do_error, handle); 2088 GNUNET_SCHEDULER_add_now (&do_error, handle);
2047 return; 2089 return;
2048 } 2090 }
2049 id_token = OIDC_id_token_new (&ticket.audience, 2091 id_token = OIDC_generate_id_token (&ticket.audience,
2050 &ticket.identity, 2092 &ticket.identity,
2051 cl, 2093 cl,
2052 al, 2094 al,
2053 &expiration_time, 2095 &expiration_time,
2054 (NULL != nonce) ? nonce : NULL, 2096 (NULL != nonce) ? nonce : NULL,
2055 jwt_secret); 2097 jwt_secret);
2056 access_token = OIDC_access_token_new (); 2098 access_token = OIDC_access_token_new (&ticket);
2057 OIDC_build_token_response (access_token, 2099 OIDC_build_token_response (access_token,
2058 id_token, 2100 id_token,
2059 &expiration_time, 2101 &expiration_time,
2060 &json_response); 2102 &json_response);
2061 2103
2062 persist_access_token (handle, access_token, &ticket);
2063 resp = GNUNET_REST_create_response (json_response); 2104 resp = GNUNET_REST_create_response (json_response);
2064 MHD_add_response_header (resp, "Cache-Control", "no-store"); 2105 MHD_add_response_header (resp, "Cache-Control", "no-store");
2065 MHD_add_response_header (resp, "Pragma", "no-cache"); 2106 MHD_add_response_header (resp, "Pragma", "no-cache");
@@ -2084,83 +2125,56 @@ consume_ticket (void *cls,
2084 const struct GNUNET_RECLAIM_Attestation *attest) 2125 const struct GNUNET_RECLAIM_Attestation *attest)
2085{ 2126{
2086 struct RequestHandle *handle = cls; 2127 struct RequestHandle *handle = cls;
2128 struct GNUNET_RECLAIM_AttributeListEntry *ale;
2129 struct GNUNET_RECLAIM_AttestationListEntry *atle;
2130 struct MHD_Response *resp;
2131 char *result_str;
2087 handle->idp_op = NULL; 2132 handle->idp_op = NULL;
2088 2133
2134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attr: %s\n", attr->name);
2089 if (NULL == identity) 2135 if (NULL == identity)
2090 { 2136 {
2091 GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); 2137 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2138 handle->attr_userinfo_list,
2139 handle->attests_list);
2140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Userinfo: %s\n", result_str);
2141 resp = GNUNET_REST_create_response (result_str);
2142 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2143 GNUNET_free (result_str);
2144 cleanup_handle (handle);
2092 return; 2145 return;
2093 } 2146 }
2094 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) 2147 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
2148 ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
2149 &attr->attestation,
2150 attr->type,
2151 attr->data,
2152 attr->data_size);
2153 ale->attribute->id = attr->id;
2154 ale->attribute->flag = attr->flag;
2155 ale->attribute->attestation = attr->attestation;
2156 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2157 handle->attr_userinfo_list->list_tail,
2158 ale);
2159 for (atle = handle->attests_list->list_head; NULL != atle; atle = atle->next)
2160 {
2161 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->attestation->id,
2162 &attest->id))
2163 continue;
2164 break; /** already in list **/
2165 }
2166 if (NULL == atle)
2095 { 2167 {
2096 char *tmp_value; 2168 /** Attestation matches for attribute, add **/
2097 json_t *value; 2169 atle = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
2098 tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type, 2170 atle->attestation = GNUNET_RECLAIM_attestation_new (attest->name,
2099 attr->data, 2171 attest->type,
2100 attr->data_size); 2172 attest->data,
2101 value = json_string (tmp_value); 2173 attest->data_size);
2102 json_object_set_new (handle->oidc->response, attr->name, value); 2174 GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head,
2103 GNUNET_free (tmp_value); 2175 handle->attests_list->list_tail,
2104 return; 2176 atle);
2105 } 2177 }
2106 json_t *claim_sources;
2107 json_t *claim_sources_jwt;
2108 json_t *claim_names;
2109 char *attest_val_str;
2110 claim_sources = json_object_get (handle->oidc->response,"_claim_sources");
2111 claim_names = json_object_get (handle->oidc->response,"_claim_names");
2112 attest_val_str =
2113 GNUNET_RECLAIM_attestation_value_to_string (attest->type,
2114 attest->data,
2115 attest->data_size);
2116 if ((NULL == claim_sources) && (NULL == claim_names) )
2117 {
2118 claim_sources = json_object ();
2119 claim_names = json_object ();
2120 }
2121 char *source_name;
2122 int i = 0;
2123 GNUNET_asprintf (&source_name, "src%d", i);
2124 while (NULL != (claim_sources_jwt = json_object_get (claim_sources,
2125 source_name)))
2126 {
2127 if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt,
2128 "JWT")),
2129 attest_val_str))
2130 {
2131 // Adapt only the claim names
2132 json_object_set_new (claim_names, attr->data,
2133 json_string (source_name));
2134 json_object_set (handle->oidc->response,
2135 "_claim_names", claim_names);
2136 break;
2137 }
2138 i++;
2139 GNUNET_free (source_name);
2140 GNUNET_asprintf (&source_name, "src%d", i);
2141 }
2142
2143 // Create new one
2144 if (NULL == claim_sources_jwt)
2145 {
2146 claim_sources_jwt = json_object ();
2147 // Set the JWT for names
2148 json_object_set_new (claim_names, attr->data,
2149 json_string (source_name));
2150 // Set the JWT for the inner source
2151 json_object_set_new (claim_sources_jwt, "JWT",
2152 json_string (attest_val_str));
2153 // Set the JWT for the source
2154 json_object_set_new (claim_sources, source_name, claim_sources_jwt);
2155 // Set as claims
2156 json_object_set (handle->oidc->response, "_claim_names", claim_names);
2157 json_object_set (handle->oidc->response, "_claim_sources",claim_sources);
2158 }
2159
2160 json_decref (claim_sources);
2161 json_decref (claim_names);
2162 json_decref (claim_sources_jwt);
2163 GNUNET_free (attest_val_str);
2164} 2178}
2165 2179
2166 2180
@@ -2178,15 +2192,16 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2178{ 2192{
2179 // TODO expiration time 2193 // TODO expiration time
2180 struct RequestHandle *handle = cls; 2194 struct RequestHandle *handle = cls;
2195 struct GNUNET_RECLAIM_Ticket *ticket;
2181 char delimiter[] = " "; 2196 char delimiter[] = " ";
2182 struct GNUNET_HashCode cache_key; 2197 struct GNUNET_HashCode cache_key;
2183 char *authorization; 2198 char *authorization;
2184 char *authorization_type; 2199 char *authorization_type;
2185 char *authorization_access_token; 2200 char *authorization_access_token;
2186 struct GNUNET_RECLAIM_Ticket *ticket; 2201 const struct EgoEntry *aud_ego;
2187 const struct EgoEntry *ego_entry;
2188 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; 2202 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
2189 2203
2204 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n");
2190 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, 2205 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
2191 strlen (OIDC_AUTHORIZATION_HEADER_KEY), 2206 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
2192 &cache_key); 2207 &cache_key);
@@ -2228,25 +2243,22 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2228 return; 2243 return;
2229 } 2244 }
2230 2245
2231 GNUNET_CRYPTO_hash (authorization_access_token, 2246 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2232 strlen (authorization_access_token), 2247 &ticket))
2233 &cache_key);
2234 if (GNUNET_NO ==
2235 GNUNET_CONTAINER_multihashmap_contains (OIDC_access_token_map,
2236 &cache_key))
2237 { 2248 {
2238 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); 2249 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2239 handle->edesc = GNUNET_strdup ("The access token expired"); 2250 handle->edesc = GNUNET_strdup ("The access token is invalid");
2240 handle->response_code = MHD_HTTP_UNAUTHORIZED; 2251 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2241 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); 2252 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2242 GNUNET_free (authorization); 2253 GNUNET_free (authorization);
2243 return; 2254 return;
2255
2244 } 2256 }
2245 ticket =
2246 GNUNET_CONTAINER_multihashmap_get (OIDC_access_token_map, &cache_key);
2247 GNUNET_assert (NULL != ticket); 2257 GNUNET_assert (NULL != ticket);
2248 ego_entry = find_ego (handle, &ticket->audience); 2258 handle->ticket = *ticket;
2249 if (NULL == ego_entry) 2259 GNUNET_free (ticket);
2260 aud_ego = find_ego (handle, &handle->ticket.audience);
2261 if (NULL == aud_ego)
2250 { 2262 {
2251 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); 2263 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
2252 handle->edesc = GNUNET_strdup ("The access token expired"); 2264 handle->edesc = GNUNET_strdup ("The access token expired");
@@ -2255,53 +2267,23 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2255 GNUNET_free (authorization); 2267 GNUNET_free (authorization);
2256 return; 2268 return;
2257 } 2269 }
2270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n");
2271 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2272 handle->attr_userinfo_list =
2273 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
2274 handle->attests_list =
2275 GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
2258 2276
2259 handle->idp = GNUNET_RECLAIM_connect (cfg); 2277 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2260 handle->oidc->response = json_object ();
2261 json_object_set_new (handle->oidc->response,
2262 "sub",
2263 json_string (ego_entry->keystring));
2264 privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
2265 handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
2266 privkey, 2278 privkey,
2267 ticket, 2279 &handle->ticket,
2268 consume_ticket, 2280 &consume_ticket,
2269 handle); 2281 handle);
2270 GNUNET_free (authorization); 2282 GNUNET_free (authorization);
2271} 2283}
2272 2284
2273 2285
2274/** 2286/**
2275 * Handle rest request
2276 *
2277 * @param handle the request handle
2278 */
2279static void
2280init_cont (struct RequestHandle *handle)
2281{
2282 struct GNUNET_REST_RequestHandlerError err;
2283 static const struct GNUNET_REST_RequestHandler handlers[] =
2284 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2285 { MHD_HTTP_METHOD_POST,
2286 GNUNET_REST_API_NS_AUTHORIZE,
2287 &authorize_endpoint }, // url-encoded
2288 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2289 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2290 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2291 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2292 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2293 GNUNET_REST_HANDLER_END };
2294
2295 if (GNUNET_NO ==
2296 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2297 {
2298 handle->response_code = err.error_code;
2299 GNUNET_SCHEDULER_add_now (&do_error, handle);
2300 }
2301}
2302
2303
2304/**
2305 * If listing is enabled, prints information about the egos. 2287 * If listing is enabled, prints information about the egos.
2306 * 2288 *
2307 * This function is initially called for all egos and then again 2289 * This function is initially called for all egos and then again
@@ -2340,18 +2322,16 @@ list_ego (void *cls,
2340 void **ctx, 2322 void **ctx,
2341 const char *identifier) 2323 const char *identifier)
2342{ 2324{
2343 struct RequestHandle *handle = cls;
2344 struct EgoEntry *ego_entry; 2325 struct EgoEntry *ego_entry;
2345 struct GNUNET_CRYPTO_EcdsaPublicKey pk; 2326 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
2346 2327
2347 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) 2328 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
2348 { 2329 {
2349 handle->state = ID_REST_STATE_POST_INIT; 2330 state = ID_REST_STATE_POST_INIT;
2350 init_cont (handle);
2351 return; 2331 return;
2352 } 2332 }
2353 GNUNET_assert (NULL != ego); 2333 GNUNET_assert (NULL != ego);
2354 if (ID_REST_STATE_INIT == handle->state) 2334 if (ID_REST_STATE_INIT == state)
2355 2335
2356 { 2336 {
2357 ego_entry = GNUNET_new (struct EgoEntry); 2337 ego_entry = GNUNET_new (struct EgoEntry);
@@ -2359,15 +2339,15 @@ list_ego (void *cls,
2359 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); 2339 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
2360 ego_entry->ego = ego; 2340 ego_entry->ego = ego;
2361 ego_entry->identifier = GNUNET_strdup (identifier); 2341 ego_entry->identifier = GNUNET_strdup (identifier);
2362 GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head, 2342 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2363 handle->ego_tail, 2343 ego_tail,
2364 ego_entry); 2344 ego_entry);
2365 return; 2345 return;
2366 } 2346 }
2367 /* Ego renamed or added */ 2347 /* Ego renamed or added */
2368 if (identifier != NULL) 2348 if (identifier != NULL)
2369 { 2349 {
2370 for (ego_entry = handle->ego_head; NULL != ego_entry; 2350 for (ego_entry = ego_head; NULL != ego_entry;
2371 ego_entry = ego_entry->next) 2351 ego_entry = ego_entry->next)
2372 { 2352 {
2373 if (ego_entry->ego == ego) 2353 if (ego_entry->ego == ego)
@@ -2386,15 +2366,15 @@ list_ego (void *cls,
2386 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); 2366 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
2387 ego_entry->ego = ego; 2367 ego_entry->ego = ego;
2388 ego_entry->identifier = GNUNET_strdup (identifier); 2368 ego_entry->identifier = GNUNET_strdup (identifier);
2389 GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head, 2369 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
2390 handle->ego_tail, 2370 ego_tail,
2391 ego_entry); 2371 ego_entry);
2392 } 2372 }
2393 } 2373 }
2394 else 2374 else
2395 { 2375 {
2396 /* Delete */ 2376 /* Delete */
2397 for (ego_entry = handle->ego_head; NULL != ego_entry; 2377 for (ego_entry = ego_head; NULL != ego_entry;
2398 ego_entry = ego_entry->next) 2378 ego_entry = ego_entry->next)
2399 { 2379 {
2400 if (ego_entry->ego == ego) 2380 if (ego_entry->ego == ego)
@@ -2403,8 +2383,8 @@ list_ego (void *cls,
2403 if (NULL == ego_entry) 2383 if (NULL == ego_entry)
2404 return; /* Not found */ 2384 return; /* Not found */
2405 2385
2406 GNUNET_CONTAINER_DLL_remove (handle->ego_head, 2386 GNUNET_CONTAINER_DLL_remove (ego_head,
2407 handle->ego_tail, 2387 ego_tail,
2408 ego_entry); 2388 ego_entry);
2409 GNUNET_free (ego_entry->identifier); 2389 GNUNET_free (ego_entry->identifier);
2410 GNUNET_free (ego_entry->keystring); 2390 GNUNET_free (ego_entry->keystring);
@@ -2415,36 +2395,153 @@ list_ego (void *cls,
2415 2395
2416 2396
2417static void 2397static void
2398oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2399 const char *url,
2400 void *cls)
2401{
2402 json_t *oidc_config;
2403 json_t *auth_methods;
2404 json_t *sig_algs;
2405 json_t *scopes;
2406 json_t *response_types;
2407 json_t *sub_types;
2408 json_t *claim_types;
2409 char *oidc_config_str;
2410 struct MHD_Response *resp;
2411 struct RequestHandle *handle = cls;
2412
2413 oidc_config = json_object ();
2414 // FIXME get from config?
2415 json_object_set_new (oidc_config,
2416 "issuer", json_string ("http://localhost:7776"));
2417 json_object_set_new (oidc_config,
2418 "authorization_endpoint",
2419 json_string ("https://api.reclaim/openid/authorize"));
2420 json_object_set_new (oidc_config,
2421 "token_endpoint",
2422 json_string ("http://localhost:7776/openid/token"));
2423 auth_methods = json_array ();
2424 json_array_append_new (auth_methods,
2425 json_string ("client_secret_basic"));
2426 json_array_append_new (auth_methods,
2427 json_string ("client_secret_post"));
2428 json_object_set_new (oidc_config,
2429 "token_endpoint_auth_methods_supported",
2430 auth_methods);
2431 sig_algs = json_array ();
2432 json_array_append_new (sig_algs,
2433 json_string ("HS512"));
2434 json_object_set_new (oidc_config,
2435 "id_token_signing_alg_values_supported",
2436 sig_algs);
2437 json_object_set_new (oidc_config,
2438 "userinfo_endpoint",
2439 json_string ("http://localhost:7776/openid/userinfo"));
2440 scopes = json_array ();
2441 json_array_append_new (scopes,
2442 json_string ("openid"));
2443 json_array_append_new (scopes,
2444 json_string ("profile"));
2445 json_object_set_new (oidc_config,
2446 "scopes_supported",
2447 scopes);
2448 response_types = json_array ();
2449 json_array_append_new (response_types,
2450 json_string ("code"));
2451 json_object_set_new (oidc_config,
2452 "response_types_supported",
2453 response_types);
2454 sub_types = json_array ();
2455 json_array_append_new (sub_types,
2456 json_string ("public")); /* no pairwise suppport */
2457 json_object_set_new (oidc_config,
2458 "subject_types_supported",
2459 sub_types);
2460 claim_types = json_array ();
2461 json_array_append_new (claim_types,
2462 json_string ("normal"));
2463 json_array_append_new (claim_types,
2464 json_string ("aggregated"));
2465 json_object_set_new (oidc_config,
2466 "claim_types_supported",
2467 claim_types);
2468 json_object_set_new (oidc_config,
2469 "claims_parameter_supported",
2470 json_boolean (1));
2471 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2472 resp = GNUNET_REST_create_response (oidc_config_str);
2473 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2474 GNUNET_free (oidc_config_str);
2475 cleanup_handle (handle);
2476}
2477
2478
2479/**
2480 * Respond to OPTIONS request
2481 *
2482 * @param con_handle the connection handle
2483 * @param url the url
2484 * @param cls the RequestHandle
2485 */
2486static void
2487oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle,
2488 const char *url,
2489 void *cls)
2490{
2491 struct MHD_Response *resp;
2492 struct RequestHandle *handle = cls;
2493
2494 // For now, independent of path return all options
2495 resp = GNUNET_REST_create_response (NULL);
2496 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
2497 MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
2498 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2499 cleanup_handle (handle);
2500 return;
2501}
2502
2503
2504static enum GNUNET_GenericReturnValue
2418rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, 2505rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
2419 GNUNET_REST_ResultProcessor proc, 2506 GNUNET_REST_ResultProcessor proc,
2420 void *proc_cls) 2507 void *proc_cls)
2421{ 2508{
2422 struct RequestHandle *handle = GNUNET_new (struct RequestHandle); 2509 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2510 struct GNUNET_REST_RequestHandlerError err;
2511 static const struct GNUNET_REST_RequestHandler handlers[] =
2512 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2513 { MHD_HTTP_METHOD_POST,
2514 GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2515 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2516 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2517 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2518 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2519 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2520 &oidc_config_endpoint },
2521 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2522 &oidc_config_cors },
2523 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2524 GNUNET_REST_HANDLER_END };
2423 2525
2424 handle->oidc = GNUNET_new (struct OIDC_Variables); 2526 handle->oidc = GNUNET_new (struct OIDC_Variables);
2425 if (NULL == OIDC_cookie_jar_map) 2527 if (NULL == OIDC_cookie_jar_map)
2426 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, 2528 OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2427 GNUNET_NO); 2529 GNUNET_NO);
2428 if (NULL == OIDC_access_token_map)
2429 OIDC_access_token_map =
2430 GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2431 handle->response_code = 0; 2530 handle->response_code = 0;
2432 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 2531 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
2433 handle->proc_cls = proc_cls; 2532 handle->proc_cls = proc_cls;
2434 handle->proc = proc; 2533 handle->proc = proc;
2435 handle->state = ID_REST_STATE_INIT;
2436 handle->rest_handle = rest_handle; 2534 handle->rest_handle = rest_handle;
2437
2438 handle->url = GNUNET_strdup (rest_handle->url); 2535 handle->url = GNUNET_strdup (rest_handle->url);
2439 if (handle->url[strlen (handle->url) - 1] == '/') 2536 if (handle->url[strlen (handle->url) - 1] == '/')
2440 handle->url[strlen (handle->url) - 1] = '\0'; 2537 handle->url[strlen (handle->url) - 1] = '\0';
2441 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); 2538 if (GNUNET_NO ==
2442 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle); 2539 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2443 handle->gns_handle = GNUNET_GNS_connect (cfg); 2540 return GNUNET_NO;
2444 handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); 2541
2445 handle->timeout_task = 2542 handle->timeout_task =
2446 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle); 2543 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); 2544 return GNUNET_YES;
2448} 2545}
2449 2546
2450 2547
@@ -2469,6 +2566,11 @@ libgnunet_plugin_rest_openid_connect_init (void *cls)
2469 api->cls = &plugin; 2566 api->cls = &plugin;
2470 api->name = GNUNET_REST_API_NS_OIDC; 2567 api->name = GNUNET_REST_API_NS_OIDC;
2471 api->process_request = &rest_identity_process_request; 2568 api->process_request = &rest_identity_process_request;
2569 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2570 gns_handle = GNUNET_GNS_connect (cfg);
2571 idp = GNUNET_RECLAIM_connect (cfg);
2572
2573 state = ID_REST_STATE_INIT;
2472 GNUNET_asprintf (&allow_methods, 2574 GNUNET_asprintf (&allow_methods,
2473 "%s, %s, %s, %s, %s", 2575 "%s, %s, %s, %s, %s",
2474 MHD_HTTP_METHOD_GET, 2576 MHD_HTTP_METHOD_GET,
@@ -2494,6 +2596,7 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
2494{ 2596{
2495 struct GNUNET_REST_Plugin *api = cls; 2597 struct GNUNET_REST_Plugin *api = cls;
2496 struct Plugin *plugin = api->cls; 2598 struct Plugin *plugin = api->cls;
2599 struct EgoEntry *ego_entry;
2497 2600
2498 plugin->cfg = NULL; 2601 plugin->cfg = NULL;
2499 2602
@@ -2508,15 +2611,23 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
2508 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); 2611 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
2509 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map); 2612 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2510 2613
2511 hashmap_it =
2512 GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_access_token_map);
2513 while (GNUNET_YES ==
2514 GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL,
2515 value))
2516 GNUNET_free (value);
2517 GNUNET_CONTAINER_multihashmap_destroy (OIDC_access_token_map);
2518 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); 2614 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
2519 GNUNET_free (allow_methods); 2615 GNUNET_free (allow_methods);
2616 if (NULL != gns_handle)
2617 GNUNET_GNS_disconnect (gns_handle);
2618 if (NULL != identity_handle)
2619 GNUNET_IDENTITY_disconnect (identity_handle);
2620 if (NULL != idp)
2621 GNUNET_RECLAIM_disconnect (idp);
2622 while (NULL != (ego_entry = ego_head))
2623 {
2624 GNUNET_CONTAINER_DLL_remove (ego_head,
2625 ego_tail,
2626 ego_entry);
2627 GNUNET_free (ego_entry->identifier);
2628 GNUNET_free (ego_entry->keystring);
2629 GNUNET_free (ego_entry);
2630 }
2520 GNUNET_free (api); 2631 GNUNET_free (api);
2521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2522 "OpenID Connect REST plugin is finished\n"); 2633 "OpenID Connect REST plugin is finished\n");