GNUnet  0.11.x
plugin_rest_openid_connect.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012-2018 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
27 #include "platform.h"
28 #include <inttypes.h>
29 #include <jansson.h>
30 
31 #include "gnunet_buffer_lib.h"
32 #include "gnunet_strings_lib.h"
33 #include "gnunet_gns_service.h"
34 #include "gnunet_gnsrecord_lib.h"
37 #include "gnunet_reclaim_lib.h"
38 #include "gnunet_reclaim_service.h"
39 #include "gnunet_rest_lib.h"
40 #include "gnunet_rest_plugin.h"
41 #include "gnunet_signatures.h"
42 #include "microhttpd.h"
43 #include "oidc_helper.h"
44 
48 #define GNUNET_REST_API_NS_OIDC "/openid"
49 
53 #define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
54 
58 #define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
59 
63 #define GNUNET_REST_API_NS_TOKEN "/openid/token"
64 
68 #define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
69 
73 #define GNUNET_REST_API_NS_LOGIN "/openid/login"
74 
78 #define ID_REST_STATE_INIT 0
79 
83 #define ID_REST_STATE_POST_INIT 1
84 
88 #define OIDC_GRANT_TYPE_KEY "grant_type"
89 
93 #define OIDC_GRANT_TYPE_VALUE "authorization_code"
94 
98 #define OIDC_CODE_KEY "code"
99 
103 #define OIDC_RESPONSE_TYPE_KEY "response_type"
104 
108 #define OIDC_CLIENT_ID_KEY "client_id"
109 
113 #define OIDC_SCOPE_KEY "scope"
114 
118 #define OIDC_REDIRECT_URI_KEY "redirect_uri"
119 
123 #define OIDC_STATE_KEY "state"
124 
128 #define OIDC_NONCE_KEY "nonce"
129 
133 #define OIDC_CLAIMS_KEY "claims"
134 
138 #define OIDC_CODE_CHALLENGE_KEY "code_challenge"
139 
143 #define OIDC_CODE_VERIFIER_KEY "code_verifier"
144 
148 #define OIDC_COOKIE_EXPIRATION 3
149 
153 #define OIDC_COOKIE_HEADER_KEY "cookie"
154 
158 #define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
159 
163 #define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
164 
168 #define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
169 
173 #define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
174 
178 #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
179 
183 #define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
184 
188 #define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
189 
193 #define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
194 
198 #define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
199 
203 #define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
204 
208 #define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
209 
213 #define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
214 
218 #define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
219 
223 #define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
224 
228 #define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
229 
230 
234 static char *OIDC_ignored_parameter_array[] = { "display",
235  "prompt",
236  "ui_locales",
237  "response_mode",
238  "id_token_hint",
239  "login_hint",
240  "acr_values" };
241 
246 
251 
255 static char *allow_methods;
256 
260 static struct EgoEntry *ego_head;
261 
265 static struct EgoEntry *ego_tail;
266 
270 static int state;
271 
276 
281 
285 static struct GNUNET_RECLAIM_Handle *idp;
286 
290 struct Plugin
291 {
292  const struct GNUNET_CONFIGURATION_Handle *cfg;
293 };
294 
299 {
303  struct GNUNET_IDENTITY_PublicKey client_pkey;
304 
308  char *client_id;
309 
314 
318  char *scope;
319 
323  char *state;
324 
328  char *nonce;
329 
333  char *claims;
334 
339 
344 
349 
354 
359 
360 };
361 
365 struct EgoEntry
366 {
370  struct EgoEntry *next;
371 
375  struct EgoEntry *prev;
376 
380  char *identifier;
381 
385  char *keystring;
386 
390  struct GNUNET_IDENTITY_Ego *ego;
391 };
392 
393 
394 struct RequestHandle
395 {
399  struct RequestHandle *next;
400 
404  struct RequestHandle *prev;
405 
409  struct EgoEntry *ego_entry;
410 
414  struct GNUNET_IDENTITY_PrivateKey priv_key;
415 
420 
425 
429  struct GNUNET_REST_RequestHandle *rest_handle;
430 
435 
440 
445 
450 
455 
456 
461 
466 
471 
472 
477 
482 
487 
492 
497 
501  void *proc_cls;
502 
506  char *url;
507 
511  char *tld;
512 
517 
522 
526  char *emsg;
527 
531  char *edesc;
532 
536  int response_code;
537 
542 };
543 
548 
553 
554 
559 static void
561 {
562 
563  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
564  if (NULL != handle->timeout_task)
566  if (NULL != handle->attr_it)
568  if (NULL != handle->cred_it)
570  if (NULL != handle->ticket_it)
572  if (NULL != handle->idp_op)
573  GNUNET_RECLAIM_cancel (handle->idp_op);
574  GNUNET_free (handle->url);
575  GNUNET_free (handle->tld);
576  GNUNET_free (handle->redirect_prefix);
577  GNUNET_free (handle->redirect_suffix);
578  GNUNET_free (handle->emsg);
579  GNUNET_free (handle->edesc);
580  if (NULL != handle->gns_op)
582  if (NULL != handle->oidc)
583  {
584  GNUNET_free (handle->oidc->client_id);
585  GNUNET_free (handle->oidc->login_identity);
586  GNUNET_free (handle->oidc->nonce);
587  GNUNET_free (handle->oidc->redirect_uri);
588  GNUNET_free (handle->oidc->response_type);
589  GNUNET_free (handle->oidc->scope);
590  GNUNET_free (handle->oidc->state);
591  GNUNET_free (handle->oidc);
592  }
593  if (NULL!=handle->attr_idtoken_list)
595  if (NULL!=handle->attr_userinfo_list)
597  if (NULL!=handle->credentials)
599  if (NULL!=handle->presentations)
601  GNUNET_CONTAINER_DLL_remove (requests_head,
602  requests_tail,
603  handle);
604  GNUNET_free (handle);
605 }
606 
607 
613 static void
614 do_error (void *cls)
615 {
616  struct RequestHandle *handle = cls;
617  struct MHD_Response *resp;
618  char *json_error;
619 
620  GNUNET_asprintf (&json_error,
621  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
622  handle->emsg,
623  (NULL != handle->edesc) ? handle->edesc : "",
624  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
625  (NULL != handle->oidc->state) ? handle->oidc->state : "",
626  (NULL != handle->oidc->state) ? "\"" : "");
627  if (0 == handle->response_code)
628  handle->response_code = MHD_HTTP_BAD_REQUEST;
629  resp = GNUNET_REST_create_response (json_error);
630  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
631  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic");
632  MHD_add_response_header (resp,
633  MHD_HTTP_HEADER_CONTENT_TYPE,
634  "application/json");
635  handle->proc (handle->proc_cls, resp, handle->response_code);
636  cleanup_handle (handle);
637  GNUNET_free (json_error);
638 }
639 
640 
647 static void
648 do_userinfo_error (void *cls)
649 {
650  struct RequestHandle *handle = cls;
651  struct MHD_Response *resp;
652  char *error;
653 
655  "Error: %s\n", handle->edesc);
656  GNUNET_asprintf (&error,
657  "error=\"%s\", error_description=\"%s\"",
658  handle->emsg,
659  (NULL != handle->edesc) ? handle->edesc : "");
660  resp = GNUNET_REST_create_response ("");
661  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
662  handle->proc (handle->proc_cls, resp, handle->response_code);
663  cleanup_handle (handle);
664  GNUNET_free (error);
665 }
666 
667 
673 static void
674 do_redirect_error (void *cls)
675 {
676  struct RequestHandle *handle = cls;
677  struct MHD_Response *resp;
678  char *redirect;
679 
680  GNUNET_asprintf (&redirect,
681  "%s?error=%s&error_description=%s%s%s",
682  handle->oidc->redirect_uri,
683  handle->emsg,
684  handle->edesc,
685  (NULL != handle->oidc->state) ? "&state=" : "",
686  (NULL != handle->oidc->state) ? handle->oidc->state : "");
687  resp = GNUNET_REST_create_response ("");
688  MHD_add_response_header (resp, "Location", redirect);
689  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
690  cleanup_handle (handle);
691  GNUNET_free (redirect);
692 }
693 
694 
700 static void
701 do_timeout (void *cls)
702 {
703  struct RequestHandle *handle = cls;
704 
705  handle->timeout_task = NULL;
706  do_error (handle);
707 }
708 
709 
717 static void
719  const char *url,
720  void *cls)
721 {
722  struct MHD_Response *resp;
723  struct RequestHandle *handle = cls;
724 
725  // For now, independent of path return all options
726  resp = GNUNET_REST_create_response (NULL);
727  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
728  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
729  cleanup_handle (handle);
730  return;
731 }
732 
733 
737 static void
739 {
740  struct GNUNET_HashCode cache_key;
741  char *cookies;
742  struct GNUNET_TIME_Absolute current_time, *relog_time;
743  char delimiter[] = "; ";
744  char *tmp_cookies;
745  char *token;
746  char *value;
747 
748  // gets identity of login try with cookie
750  strlen (OIDC_COOKIE_HEADER_KEY),
751  &cache_key);
754  &cache_key))
755  {
756  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
757  return;
758  }
759  // splits cookies and find 'Identity' cookie
760  tmp_cookies =
762  &cache_key);
763  cookies = GNUNET_strdup (tmp_cookies);
764  token = strtok (cookies, delimiter);
765  handle->oidc->user_cancelled = GNUNET_NO;
766  handle->oidc->login_identity = NULL;
767  if (NULL == token)
768  {
770  "Unable to parse cookie: %s\n",
771  cookies);
772  GNUNET_free (cookies);
773  return;
774  }
775 
776  while (NULL != token)
777  {
778  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
779  {
780  handle->oidc->user_cancelled = GNUNET_YES;
781  GNUNET_free (cookies);
782  return;
783  }
784  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
785  break;
786  token = strtok (NULL, delimiter);
787  }
788  if (NULL == token)
789  {
791  "No cookie value to process: %s\n",
792  cookies);
793  GNUNET_free (cookies);
794  return;
795  }
796  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
797  if (GNUNET_NO ==
798  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
799  {
800  GNUNET_log (
802  "Found cookie `%s', but no corresponding expiration entry present...\n",
803  token);
804  GNUNET_free (cookies);
805  return;
806  }
807  relog_time =
808  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
809  current_time = GNUNET_TIME_absolute_get ();
810  // 30 min after old login -> redirect to login
811  if (current_time.abs_value_us > relog_time->abs_value_us)
812  {
814  "Found cookie `%s', but it is expired.\n",
815  token);
816  GNUNET_free (cookies);
817  return;
818  }
819  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
820  GNUNET_assert (NULL != value);
821  handle->oidc->login_identity = GNUNET_strdup (value);
822  GNUNET_free (cookies);
823 }
824 
825 
829 static void
830 login_redirect (void *cls)
831 {
832  char *login_base_url;
833  char *new_redirect;
834  char *tmp;
835  struct MHD_Response *resp;
836  struct GNUNET_Buffer buf = { 0 };
837  struct RequestHandle *handle = cls;
838 
840  "reclaim-rest-plugin",
841  "address",
842  &login_base_url))
843  {
844  GNUNET_buffer_write_str (&buf, login_base_url);
846  "?%s=%s",
848  handle->oidc->response_type);
850  "&%s=%s",
852  handle->oidc->client_id);
854  strlen (handle->oidc->redirect_uri),
855  &tmp);
857  "&%s=%s",
859  tmp);
860  GNUNET_free (tmp);
862  strlen (handle->oidc->scope),
863  &tmp);
865  "&%s=%s",
867  tmp);
868  GNUNET_free (tmp);
869  if (NULL != handle->oidc->state)
870  {
872  strlen (handle->oidc->state),
873  &tmp);
875  "&%s=%s",
877  handle->oidc->state);
878  GNUNET_free (tmp);
879  }
880  if (NULL != handle->oidc->code_challenge)
881  {
883  "&%s=%s",
885  handle->oidc->code_challenge);
886  }
887  if (NULL != handle->oidc->nonce)
888  {
890  "&%s=%s",
892  handle->oidc->nonce);
893  }
894  if (NULL != handle->oidc->claims)
895  {
897  strlen (handle->oidc->claims),
898  &tmp);
900  "&%s=%s",
902  tmp);
903  GNUNET_free (tmp);
904  }
905  new_redirect = GNUNET_buffer_reap_str (&buf);
906  resp = GNUNET_REST_create_response ("");
907  MHD_add_response_header (resp, "Location", new_redirect);
908  GNUNET_free (login_base_url);
909  }
910  else
911  {
913  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
914  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
916  return;
917  }
918  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
919  GNUNET_free (new_redirect);
920  cleanup_handle (handle);
921 }
922 
923 
927 static void
929 {
930  struct RequestHandle *handle = cls;
931 
933  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
935 }
936 
937 
942 static void
944  const struct GNUNET_RECLAIM_Ticket *ticket,
945  const struct GNUNET_RECLAIM_PresentationList *pres)
946 {
947  struct RequestHandle *handle = cls;
948  struct MHD_Response *resp;
949  char *ticket_str;
950  char *redirect_uri;
951  char *code_string;
952 
953  handle->idp_op = NULL;
954  if (NULL == ticket)
955  {
957  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
959  return;
960  }
961  handle->ticket = *ticket;
962  ticket_str =
964  sizeof(struct GNUNET_RECLAIM_Ticket));
965  code_string = OIDC_build_authz_code (&handle->priv_key,
966  &handle->ticket,
967  handle->attr_idtoken_list,
968  pres,
969  handle->oidc->nonce,
970  handle->oidc->code_challenge);
971  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
972  (NULL != handle->tld))
973  {
974  GNUNET_asprintf (&redirect_uri,
975  "%s.%s/%s%s%s=%s&state=%s",
976  handle->redirect_prefix,
977  handle->tld,
978  handle->redirect_suffix,
979  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
980  "&"),
981  handle->oidc->response_type,
982  code_string,
983  handle->oidc->state);
984  }
985  else
986  {
987  GNUNET_asprintf (&redirect_uri,
988  "%s%s%s=%s&state=%s",
989  handle->oidc->redirect_uri,
990  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
991  "&"),
992  handle->oidc->response_type,
993  code_string,
994  handle->oidc->state);
995  }
996  resp = GNUNET_REST_create_response ("");
997  MHD_add_response_header (resp, "Location", redirect_uri);
998  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
999  cleanup_handle (handle);
1000  GNUNET_free (redirect_uri);
1001  GNUNET_free (ticket_str);
1002  GNUNET_free (code_string);
1003 }
1004 
1005 
1006 static struct GNUNET_RECLAIM_AttributeList*
1008  struct GNUNET_RECLAIM_AttributeList *list_b)
1009 {
1010  struct GNUNET_RECLAIM_AttributeList *merged_list;
1011  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1012  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1013  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1014 
1015  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1016  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1017  {
1020  &le_a->attribute->
1021  credential,
1022  le_a->attribute->type,
1023  le_a->attribute->data,
1024  le_a->attribute->data_size);
1025  le_m->attribute->id = le_a->attribute->id;
1026  le_m->attribute->flag = le_a->attribute->flag;
1027  le_m->attribute->credential = le_a->attribute->credential;
1028  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1029  merged_list->list_tail,
1030  le_m);
1031  }
1032  le_m = NULL;
1033  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1034  {
1035  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1036  {
1038  &le_b->attribute->id))
1039  break;
1040  }
1041  if (NULL != le_m)
1042  continue;
1045  &le_b->attribute->
1046  credential,
1047  le_b->attribute->type,
1048  le_b->attribute->data,
1049  le_b->attribute->data_size);
1050  le_m->attribute->id = le_b->attribute->id;
1051  le_m->attribute->flag = le_b->attribute->flag;
1052  le_m->attribute->credential = le_b->attribute->credential;
1053  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1054  merged_list->list_tail,
1055  le_m);
1056  }
1057  return merged_list;
1058 }
1059 
1060 
1061 static void
1063 {
1064  struct RequestHandle *handle = cls;
1065  struct GNUNET_RECLAIM_AttributeList *merged_list;
1066  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1067 
1068  handle->cred_it = NULL;
1069  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1070  handle->attr_userinfo_list);
1071  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1073  "List Attibute in ticket to issue: %s\n",
1074  le_m->attribute->name);
1075  handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1076  &handle->priv_key,
1077  &handle->oidc->client_pkey,
1078  merged_list,
1080  handle);
1082 }
1083 
1084 
1088 static void
1090  const struct GNUNET_IDENTITY_PublicKey *identity,
1091  const struct GNUNET_RECLAIM_Credential *cred)
1092 {
1093  struct RequestHandle *handle = cls;
1096 
1097  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1098  {
1100  &cred->id))
1101  continue;
1104  return;
1105  }
1106 
1107  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1108  {
1110  &cred->id))
1111  continue;
1115  cred->type,
1116  cred->data,
1117  cred->data_size);
1119  handle->credentials->list_tail,
1120  ale);
1121  }
1123 }
1124 
1125 
1126 static void
1128 {
1129  struct RequestHandle *handle = cls;
1130 
1131  handle->attr_it = NULL;
1132  handle->ticket_it = NULL;
1133  if (NULL == handle->attr_idtoken_list->list_head)
1134  {
1136  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1138  return;
1139  }
1141  handle->cred_it =
1143  &handle->priv_key,
1145  handle,
1147  handle,
1149  handle);
1150 
1151 }
1152 
1153 
1154 static int
1156  const char *attr_name,
1157  const char *claims_parameter)
1158 {
1159  int ret = GNUNET_NO;
1160  json_t *root;
1161  json_error_t error;
1162  json_t *claims_j;
1163  const char *key;
1164  json_t *value;
1165 
1168  attr_name))
1169  return GNUNET_YES;
1170 
1172  if ((NULL != handle->oidc->claims) &&
1173  (GNUNET_YES != ret))
1174  {
1175  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1176  claims_j = json_object_get (root, claims_parameter);
1177  /* obj is a JSON object */
1178  if (NULL != claims_j)
1179  {
1180  json_object_foreach (claims_j, key, value) {
1181  if (0 != strcmp (attr_name, key))
1182  continue;
1183  ret = GNUNET_YES;
1184  break;
1185  }
1186  }
1187  json_decref (root);
1188  }
1189  return ret;
1190 }
1191 
1192 
1193 static int
1195  const char *attr_name)
1196 {
1197  return attr_in_claims_request (handle, attr_name, "id_token");
1198 }
1199 
1200 
1201 static int
1203  const char *attr_name)
1204 {
1205  return attr_in_claims_request (handle, attr_name, "userinfo");
1206 }
1207 
1208 
1212 static void
1214  const struct GNUNET_IDENTITY_PublicKey *identity,
1215  const struct GNUNET_RECLAIM_Attribute *attr)
1216 {
1217  struct RequestHandle *handle = cls;
1219  if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1220  {
1223  &attr->credential,
1224  attr->type,
1225  attr->data,
1226  attr->data_size);
1227  le->attribute->id = attr->id;
1228  le->attribute->flag = attr->flag;
1229  le->attribute->credential = attr->credential;
1231  handle->attr_idtoken_list->list_tail,
1232  le);
1233  }
1234  if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1235  {
1238  &attr->credential,
1239  attr->type,
1240  attr->data,
1241  attr->data_size);
1242  le->attribute->id = attr->id;
1243  le->attribute->flag = attr->flag;
1244  le->attribute->credential = attr->credential;
1246  handle->attr_userinfo_list->list_tail,
1247  le);
1248  }
1249 
1251 }
1252 
1253 
1257 static void
1258 code_redirect (void *cls)
1259 {
1260  struct RequestHandle *handle = cls;
1261  struct GNUNET_TIME_Absolute current_time;
1262  struct GNUNET_TIME_Absolute *relog_time;
1263  struct GNUNET_IDENTITY_PublicKey pubkey;
1264  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1265  struct GNUNET_HashCode cache_key;
1266  char *identity_cookie;
1267 
1268  GNUNET_asprintf (&identity_cookie,
1269  "Identity=%s",
1270  handle->oidc->login_identity);
1271  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1272  GNUNET_free (identity_cookie);
1273  // No login time for identity -> redirect to login
1274  if (GNUNET_YES ==
1275  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1276  {
1277  relog_time =
1278  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1279  current_time = GNUNET_TIME_absolute_get ();
1280  // 30 min after old login -> redirect to login
1281  if (current_time.abs_value_us <= relog_time->abs_value_us)
1282  {
1283  if (GNUNET_OK !=
1285  ->login_identity,
1286  &pubkey))
1287  {
1289  handle->edesc =
1290  GNUNET_strdup ("The cookie of a login identity is not valid");
1292  return;
1293  }
1294  // iterate over egos and compare their public key
1295  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1296  handle->ego_entry = handle->ego_entry->next)
1297  {
1298  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1299  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1300  {
1301  handle->priv_key =
1303  handle->attr_idtoken_list =
1305  handle->attr_userinfo_list =
1307  handle->attr_it =
1309  &handle->priv_key,
1311  handle,
1313  handle,
1315  handle);
1316  return;
1317  }
1318  }
1320  return;
1321  }
1322  }
1323 }
1324 
1325 
1326 static void
1327 build_redirect (void *cls)
1328 {
1329  struct RequestHandle *handle = cls;
1330  struct MHD_Response *resp;
1331  char *redirect_uri;
1332 
1333  if (GNUNET_YES == handle->oidc->user_cancelled)
1334  {
1335  if ((NULL != handle->redirect_prefix) &&
1336  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1337  {
1338  GNUNET_asprintf (&redirect_uri,
1339  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1340  handle->redirect_prefix,
1341  handle->tld,
1342  handle->redirect_suffix,
1343  "access_denied",
1344  "User denied access",
1345  handle->oidc->state);
1346  }
1347  else
1348  {
1349  GNUNET_asprintf (&redirect_uri,
1350  "%s?error=%s&error_description=%s&state=%s",
1351  handle->oidc->redirect_uri,
1352  "access_denied",
1353  "User denied access",
1354  handle->oidc->state);
1355  }
1356  resp = GNUNET_REST_create_response ("");
1357  MHD_add_response_header (resp, "Location", redirect_uri);
1358  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1359  cleanup_handle (handle);
1360  GNUNET_free (redirect_uri);
1361  return;
1362  }
1364 }
1365 
1366 
1367 static void
1369  uint32_t rd_count,
1370  const struct GNUNET_GNSRECORD_Data *rd)
1371 {
1372  struct RequestHandle *handle = cls;
1373  char *tmp;
1374  char *tmp_key_str;
1375  char *pos;
1376  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1377 
1378  handle->gns_op = NULL;
1379  if (0 == rd_count)
1380  {
1382  handle->edesc =
1383  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1385  return;
1386  }
1387  for (int i = 0; i < rd_count; i++)
1388  {
1389  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1390  continue;
1391  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1392  continue;
1393  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1394  if (NULL == strstr (tmp, handle->oidc->client_id))
1395  {
1397  "Redirect uri %s does not contain client_id %s\n",
1398  tmp,
1399  handle->oidc->client_id);
1400  }
1401  else
1402  {
1403  pos = strrchr (tmp, (unsigned char) '.');
1404  if (NULL == pos)
1405  {
1407  "Redirect uri %s contains client_id but is malformed\n",
1408  tmp);
1409  GNUNET_free (tmp);
1410  continue;
1411  }
1412  *pos = '\0';
1413  handle->redirect_prefix = GNUNET_strdup (tmp);
1414  tmp_key_str = pos + 1;
1415  pos = strchr (tmp_key_str, (unsigned char) '/');
1416  if (NULL == pos)
1417  {
1419  "Redirect uri %s contains client_id but is malformed\n",
1420  tmp);
1421  GNUNET_free (tmp);
1422  continue;
1423  }
1424  *pos = '\0';
1425  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1426 
1427  GNUNET_STRINGS_string_to_data (tmp_key_str,
1428  strlen (tmp_key_str),
1429  &redirect_zone,
1430  sizeof(redirect_zone));
1431  }
1433  GNUNET_free (tmp);
1434  return;
1435  }
1437  handle->edesc =
1438  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1440 }
1441 
1442 
1446 static void
1447 client_redirect (void *cls)
1448 {
1449  struct RequestHandle *handle = cls;
1450 
1451  /* Lookup client redirect uri to verify request */
1452  handle->gns_op =
1453  GNUNET_GNS_lookup (gns_handle,
1455  &handle->oidc->client_pkey,
1459  handle);
1460 }
1461 
1462 
1463 static char *
1464 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1465 {
1466  struct GNUNET_HashCode hc;
1467  char *value;
1468  char *res;
1469 
1470  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1472  ->url_param_map,
1473  &hc))
1474  return NULL;
1475  value =
1477  if (NULL == value)
1478  return NULL;
1479  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1480  return res;
1481 }
1482 
1483 
1490 static void
1492 {
1493  struct RequestHandle *handle = cls;
1494  struct GNUNET_HashCode cache_key;
1495 
1496  char *expected_scope;
1497  char delimiter[] = " ";
1498  int number_of_ignored_parameter, iterator;
1499 
1500 
1501  // REQUIRED value: redirect_uri
1502  handle->oidc->redirect_uri =
1504  if (NULL == handle->oidc->redirect_uri)
1505  {
1507  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1509  return;
1510  }
1511 
1512  // REQUIRED value: response_type
1513  handle->oidc->response_type =
1515  if (NULL == handle->oidc->response_type)
1516  {
1518  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1520  return;
1521  }
1522 
1523  // REQUIRED value: scope
1524  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1525  if (NULL == handle->oidc->scope)
1526  {
1528  handle->edesc = GNUNET_strdup ("missing parameter scope");
1530  return;
1531  }
1532 
1533  // OPTIONAL value: nonce
1534  handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1535 
1536  // OPTIONAL value: claims
1537  handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1538 
1539  // TODO check other values if needed
1540  number_of_ignored_parameter =
1541  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1542  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1543  {
1545  strlen (OIDC_ignored_parameter_array[iterator]),
1546  &cache_key);
1547  if (GNUNET_YES ==
1549  ->url_param_map,
1550  &cache_key))
1551  {
1553  GNUNET_asprintf (&handle->edesc,
1554  "Server will not handle parameter: %s",
1555  OIDC_ignored_parameter_array[iterator]);
1557  return;
1558  }
1559  }
1560 
1561  // We only support authorization code flows.
1562  if (0 != strcmp (handle->oidc->response_type,
1564  {
1566  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1567  "obtaining this authorization code.");
1569  return;
1570  }
1571 
1572  // Checks if scope contains 'openid'
1573  expected_scope = GNUNET_strdup (handle->oidc->scope);
1574  char *test;
1575  test = strtok (expected_scope, delimiter);
1576  while (NULL != test)
1577  {
1578  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1579  break;
1580  test = strtok (NULL, delimiter);
1581  }
1582  if (NULL == test)
1583  {
1585  handle->edesc =
1586  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1588  GNUNET_free (expected_scope);
1589  return;
1590  }
1591 
1592  GNUNET_free (expected_scope);
1593  if ((NULL == handle->oidc->login_identity) &&
1594  (GNUNET_NO == handle->oidc->user_cancelled))
1596  else
1598 }
1599 
1600 
1604 static void
1605 tld_iter (void *cls, const char *section, const char *option, const char *value)
1606 {
1607  struct RequestHandle *handle = cls;
1608  struct GNUNET_IDENTITY_PublicKey pkey;
1609 
1610  if (GNUNET_OK !=
1612  {
1613  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1614  return;
1615  }
1616  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1617  handle->tld = GNUNET_strdup (option + 1);
1618 }
1619 
1620 
1628 static void
1630  const char *url,
1631  void *cls)
1632 {
1633  struct RequestHandle *handle = cls;
1634  struct EgoEntry *tmp_ego;
1635  const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1636  struct GNUNET_IDENTITY_PublicKey pkey;
1637 
1639 
1640  // RECOMMENDED value: state - REQUIRED for answers
1641  handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1642 
1643  // REQUIRED value: client_id
1645  if (NULL == handle->oidc->client_id)
1646  {
1648  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1649  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1651  return;
1652  }
1653 
1654  // OPTIONAL value: code_challenge
1655  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1657  if (NULL == handle->oidc->code_challenge)
1658  {
1660  "OAuth authorization request does not contain PKCE parameters!\n");
1661  }
1662 
1663  if (GNUNET_OK !=
1665  &handle->oidc->client_pkey))
1666  {
1668  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1669  "authorization code using this method.");
1670  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1672  return;
1673  }
1674 
1675  // If we know this identity, translated the corresponding TLD
1676  // TODO: We might want to have a reverse lookup functionality for TLDs?
1677  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1678  {
1679  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1680  GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1681  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1682  {
1683  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1684  handle->ego_entry = ego_tail;
1685  }
1686  }
1687  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1688  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n", handle->oidc->scope);
1689  if (NULL == handle->tld)
1691  if (NULL == handle->tld)
1692  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1694 }
1695 
1696 
1704 static void
1706  const char *url,
1707  void *cls)
1708 {
1709  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1710  struct RequestHandle *handle = cls;
1711  struct GNUNET_HashCode cache_key;
1712  struct GNUNET_TIME_Absolute *current_time;
1713  struct GNUNET_TIME_Absolute *last_time;
1714  char *cookie;
1715  char *header_val;
1716  json_t *root;
1717  json_error_t error;
1718  json_t *identity;
1719  char term_data[handle->rest_handle->data_size + 1];
1720 
1721  term_data[handle->rest_handle->data_size] = '\0';
1722  GNUNET_memcpy (term_data,
1723  handle->rest_handle->data,
1724  handle->rest_handle->data_size);
1725  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1726  identity = json_object_get (root, "identity");
1727  if (! json_is_string (identity))
1728  {
1730  "Error parsing json string from %s\n",
1731  term_data);
1732  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1733  json_decref (root);
1734  cleanup_handle (handle);
1735  return;
1736  }
1737  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1738  GNUNET_asprintf (&header_val,
1739  "%s;Max-Age=%d",
1740  cookie,
1742  MHD_add_response_header (resp, "Set-Cookie", header_val);
1743  MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
1744  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1745 
1746  if (0 != strcmp (json_string_value (identity), "Denied"))
1747  {
1748  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1749  *current_time = GNUNET_TIME_relative_to_absolute (
1752  last_time =
1753  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1754  GNUNET_free (last_time);
1755  GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1756  &cache_key,
1757  current_time,
1759  }
1760  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1761  GNUNET_free (cookie);
1762  GNUNET_free (header_val);
1763  json_decref (root);
1764  cleanup_handle (handle);
1765 }
1766 
1767 
1768 static int
1770  char **client_id,
1771  char **client_secret)
1772 {
1773  struct GNUNET_HashCode cache_key;
1774  char *authorization;
1775  char *credentials;
1776  char *basic_authorization;
1777  char *client_id_tmp;
1778  char *pass;
1779 
1782  &cache_key);
1784  ->header_param_map,
1785  &cache_key))
1786  return GNUNET_SYSERR;
1787  authorization =
1789  &cache_key);
1790 
1791  // split header in "Basic" and [content]
1792  credentials = strtok (authorization, " ");
1793  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1794  return GNUNET_SYSERR;
1795  credentials = strtok (NULL, " ");
1796  if (NULL == credentials)
1797  return GNUNET_SYSERR;
1798  GNUNET_STRINGS_base64_decode (credentials,
1799  strlen (credentials),
1800  (void **) &basic_authorization);
1801 
1802  if (NULL == basic_authorization)
1803  return GNUNET_SYSERR;
1804  client_id_tmp = strtok (basic_authorization, ":");
1805  if (NULL == client_id_tmp)
1806  {
1807  GNUNET_free (basic_authorization);
1808  return GNUNET_SYSERR;
1809  }
1810  pass = strtok (NULL, ":");
1811  if (NULL == pass)
1812  {
1813  GNUNET_free (basic_authorization);
1814  return GNUNET_SYSERR;
1815  }
1816  *client_id = strdup (client_id_tmp);
1817  *client_secret = strdup (pass);
1818  GNUNET_free (basic_authorization);
1819  return GNUNET_OK;
1820 }
1821 
1822 
1823 static int
1825  char **client_id,
1826  char **client_secret)
1827 {
1828  struct GNUNET_HashCode cache_key;
1829  char *client_id_tmp;
1830  char *pass;
1831 
1832  GNUNET_CRYPTO_hash ("client_id",
1833  strlen ("client_id"),
1834  &cache_key);
1836  ->url_param_map,
1837  &cache_key))
1838  return GNUNET_SYSERR;
1839  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1840  handle->rest_handle->url_param_map,
1841  &cache_key);
1842  if (NULL == client_id_tmp)
1843  return GNUNET_SYSERR;
1844  *client_id = strdup (client_id_tmp);
1845  GNUNET_CRYPTO_hash ("client_secret",
1846  strlen ("client_secret"),
1847  &cache_key);
1849  ->url_param_map,
1850  &cache_key))
1851  return GNUNET_SYSERR;
1853  &cache_key);
1854  if (NULL == pass)
1855  return GNUNET_SYSERR;
1856  *client_secret = strdup (pass);
1857  return GNUNET_OK;
1858 }
1859 
1860 
1861 static int
1863  struct GNUNET_IDENTITY_PublicKey *cid)
1864 {
1865  char *expected_pass;
1866  char *received_cid;
1867  char *received_cpw;
1868  char *pkce_cv;
1869 
1870  if (GNUNET_OK == parse_credentials_basic_auth (handle,
1871  &received_cid,
1872  &received_cpw))
1873  {
1875  "Received client credentials in HTTP AuthZ header\n");
1876  }
1877  else if (GNUNET_OK == parse_credentials_post_body (handle,
1878  &received_cid,
1879  &received_cpw))
1880  {
1882  "Received client credentials in POST body\n");
1883  }
1884  else
1885  {
1887  pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1888  if (NULL == pkce_cv)
1889  {
1891  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1892  return GNUNET_SYSERR;
1893  }
1894  handle->public_client = GNUNET_YES;
1895  GNUNET_free (pkce_cv);
1896  received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1897  GNUNET_STRINGS_string_to_data (received_cid,
1898  strlen (received_cid),
1899  cid,
1900  sizeof(struct GNUNET_IDENTITY_PublicKey));
1901  GNUNET_free (received_cid);
1902  return GNUNET_OK;
1903 
1904  }
1905 
1906  // check client password
1908  "reclaim-rest-plugin",
1909  "OIDC_CLIENT_SECRET",
1910  &expected_pass))
1911  {
1912  if (0 != strcmp (expected_pass, received_cpw))
1913  {
1914  GNUNET_free (expected_pass);
1916  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1917  return GNUNET_SYSERR;
1918  }
1919  GNUNET_free (expected_pass);
1920  }
1921  else
1922  {
1924  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1925  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1926  return GNUNET_SYSERR;
1927  }
1928  // check client_id
1929  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1930  handle->ego_entry = handle->ego_entry->next)
1931  {
1932  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1933  break;
1934  }
1935  if (NULL == handle->ego_entry)
1936  {
1937  GNUNET_free (received_cpw);
1938  GNUNET_free (received_cid);
1940  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1941  return GNUNET_SYSERR;
1942  }
1943  GNUNET_STRINGS_string_to_data (received_cid,
1944  strlen (received_cid),
1945  cid,
1946  sizeof(struct GNUNET_IDENTITY_PublicKey));
1947 
1948  GNUNET_free (received_cpw);
1949  GNUNET_free (received_cid);
1950  return GNUNET_OK;
1951 }
1952 
1953 
1954 const struct EgoEntry *
1956  struct GNUNET_IDENTITY_PublicKey *test_key)
1957 {
1958  struct EgoEntry *ego_entry;
1959  struct GNUNET_IDENTITY_PublicKey pub_key;
1960 
1961  for (ego_entry = ego_head; NULL != ego_entry;
1962  ego_entry = ego_entry->next)
1963  {
1964  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
1965  if (0 == GNUNET_memcmp (&pub_key, test_key))
1966  return ego_entry;
1967  }
1968  return NULL;
1969 }
1970 
1971 
1979 static void
1981  const char *url,
1982  void *cls)
1983 {
1984  struct RequestHandle *handle = cls;
1985  const struct EgoEntry *ego_entry;
1986  struct GNUNET_TIME_Relative expiration_time;
1987  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
1988  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
1989  struct GNUNET_RECLAIM_Ticket ticket;
1990  struct GNUNET_IDENTITY_PublicKey cid;
1991  struct GNUNET_HashCode cache_key;
1992  struct MHD_Response *resp;
1993  char *grant_type;
1994  char *code;
1995  char *json_response;
1996  char *id_token;
1997  char *access_token;
1998  char *jwt_secret;
1999  char *nonce;
2000  char *code_verifier;
2001 
2002  /*
2003  * Check Authorization
2004  */
2005  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2006  {
2008  "OIDC authorization for token endpoint failed\n");
2010  return;
2011  }
2012 
2013  /*
2014  * Check parameter
2015  */
2016 
2017  // TODO Do not allow multiple equal parameter names
2018  // REQUIRED grant_type
2020  strlen (OIDC_GRANT_TYPE_KEY),
2021  &cache_key);
2022  grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2023  if (NULL == grant_type)
2024  {
2026  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2027  handle->response_code = MHD_HTTP_BAD_REQUEST;
2029  return;
2030  }
2031 
2032  // Check parameter grant_type == "authorization_code"
2033  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2034  {
2036  handle->response_code = MHD_HTTP_BAD_REQUEST;
2037  GNUNET_free (grant_type);
2039  return;
2040  }
2041  GNUNET_free (grant_type);
2042  // REQUIRED code
2043  code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2044  if (NULL == code)
2045  {
2047  handle->edesc = GNUNET_strdup ("missing parameter code");
2048  handle->response_code = MHD_HTTP_BAD_REQUEST;
2050  return;
2051  }
2052  ego_entry = find_ego (handle, &cid);
2053  if (NULL == ego_entry)
2054  {
2056  handle->edesc = GNUNET_strdup ("Unknown client");
2057  handle->response_code = MHD_HTTP_BAD_REQUEST;
2058  GNUNET_free (code);
2060  return;
2061  }
2062 
2063  // REQUIRED code verifier
2064  code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2065  if (NULL == code_verifier)
2066  {
2068  "OAuth authorization request does not contain PKCE parameters!\n");
2069 
2070  }
2071 
2072  // decode code
2073  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2074  &cl, &pl, &nonce))
2075  {
2077  handle->edesc = GNUNET_strdup ("invalid code");
2078  handle->response_code = MHD_HTTP_BAD_REQUEST;
2079  GNUNET_free (code);
2081  return;
2082  }
2083  GNUNET_free (code);
2084 
2085  // create jwt
2087  "reclaim-rest-plugin",
2088  "expiration_time",
2089  &expiration_time))
2090  {
2092  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2093  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2095  return;
2096  }
2097 
2098 
2099  // TODO OPTIONAL acr,amr,azp
2101  "reclaim-rest-plugin",
2102  "jwt_secret",
2103  &jwt_secret))
2104  {
2106  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2107  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2109  return;
2110  }
2111  id_token = OIDC_generate_id_token (&ticket.audience,
2112  &ticket.identity,
2113  cl,
2114  pl,
2115  &expiration_time,
2116  (NULL != nonce) ? nonce : NULL,
2117  jwt_secret);
2118  access_token = OIDC_access_token_new (&ticket);
2119  OIDC_build_token_response (access_token,
2120  id_token,
2121  &expiration_time,
2122  &json_response);
2123 
2124  resp = GNUNET_REST_create_response (json_response);
2125  MHD_add_response_header (resp, "Cache-Control", "no-store");
2126  MHD_add_response_header (resp, "Pragma", "no-cache");
2127  MHD_add_response_header (resp, "Content-Type", "application/json");
2128  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2131  GNUNET_free (access_token);
2132  GNUNET_free (json_response);
2133  GNUNET_free (id_token);
2134  cleanup_handle (handle);
2135 }
2136 
2137 
2141 static void
2142 consume_ticket (void *cls,
2143  const struct GNUNET_IDENTITY_PublicKey *identity,
2144  const struct GNUNET_RECLAIM_Attribute *attr,
2145  const struct GNUNET_RECLAIM_Presentation *pres)
2146 {
2147  struct RequestHandle *handle = cls;
2150  struct MHD_Response *resp;
2151  char *result_str;
2152  handle->idp_op = NULL;
2153 
2154  if (NULL == identity)
2155  {
2156  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2157  handle->attr_userinfo_list,
2158  handle->presentations);
2159  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2160  resp = GNUNET_REST_create_response (result_str);
2161  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2162  GNUNET_free (result_str);
2163  cleanup_handle (handle);
2164  return;
2165  }
2168  &attr->credential,
2169  attr->type,
2170  attr->data,
2171  attr->data_size);
2172  ale->attribute->id = attr->id;
2173  ale->attribute->flag = attr->flag;
2174  ale->attribute->credential = attr->credential;
2176  handle->attr_userinfo_list->list_tail,
2177  ale);
2178  if (NULL == pres)
2179  return;
2180  for (atle = handle->presentations->list_head;
2181  NULL != atle; atle = atle->next)
2182  {
2184  &pres->credential_id))
2185  continue;
2186  break;
2187  }
2188  if (NULL == atle)
2189  {
2193  pres->data,
2194  pres->data_size);
2196  handle->presentations->list_tail,
2197  atle);
2198  }
2199 }
2200 
2201 
2209 static void
2211  const char *url,
2212  void *cls)
2213 {
2214  // TODO expiration time
2215  struct RequestHandle *handle = cls;
2216  struct GNUNET_RECLAIM_Ticket *ticket;
2217  char delimiter[] = " ";
2218  struct GNUNET_HashCode cache_key;
2219  char *authorization;
2220  char *authorization_type;
2221  char *authorization_access_token;
2222  const struct EgoEntry *aud_ego;
2223  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2224 
2225  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n");
2228  &cache_key);
2230  ->header_param_map,
2231  &cache_key))
2232  {
2234  handle->edesc = GNUNET_strdup ("No Access Token");
2235  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2237  return;
2238  }
2239  authorization =
2241  &cache_key);
2242 
2243  // split header in "Bearer" and access_token
2244  authorization = GNUNET_strdup (authorization);
2245  authorization_type = strtok (authorization, delimiter);
2246  if ((NULL == authorization_type) ||
2247  (0 != strcmp ("Bearer", authorization_type)))
2248  {
2250  handle->edesc = GNUNET_strdup ("No Access Token");
2251  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2253  GNUNET_free (authorization);
2254  return;
2255  }
2256  authorization_access_token = strtok (NULL, delimiter);
2257  if (NULL == authorization_access_token)
2258  {
2260  handle->edesc = GNUNET_strdup ("Access token missing");
2261  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2263  GNUNET_free (authorization);
2264  return;
2265  }
2266 
2267  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2268  &ticket))
2269  {
2271  handle->edesc = GNUNET_strdup ("The access token is invalid");
2272  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2274  GNUNET_free (authorization);
2275  return;
2276 
2277  }
2278  GNUNET_assert (NULL != ticket);
2279  handle->ticket = *ticket;
2280  GNUNET_free (ticket);
2281  aud_ego = find_ego (handle, &handle->ticket.audience);
2282  if (NULL == aud_ego)
2283  {
2285  handle->edesc = GNUNET_strdup ("The access token expired");
2286  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2288  GNUNET_free (authorization);
2289  return;
2290  }
2291  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n");
2292  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2293  handle->attr_userinfo_list =
2295  handle->presentations =
2297 
2298  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2299  privkey,
2300  &handle->ticket,
2301  &consume_ticket,
2302  handle);
2303  GNUNET_free (authorization);
2304 }
2305 
2306 
2340 static void
2341 list_ego (void *cls,
2342  struct GNUNET_IDENTITY_Ego *ego,
2343  void **ctx,
2344  const char *identifier)
2345 {
2346  struct EgoEntry *ego_entry;
2347  struct GNUNET_IDENTITY_PublicKey pk;
2348 
2349  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
2350  {
2352  return;
2353  }
2354  GNUNET_assert (NULL != ego);
2355  if (ID_REST_STATE_INIT == state)
2356 
2357  {
2358  ego_entry = GNUNET_new (struct EgoEntry);
2361  ego_entry->ego = ego;
2362  ego_entry->identifier = GNUNET_strdup (identifier);
2364  ego_tail,
2365  ego_entry);
2366  return;
2367  }
2368  /* Ego renamed or added */
2369  if (identifier != NULL)
2370  {
2371  for (ego_entry = ego_head; NULL != ego_entry;
2372  ego_entry = ego_entry->next)
2373  {
2374  if (ego_entry->ego == ego)
2375  {
2376  /* Rename */
2377  GNUNET_free (ego_entry->identifier);
2378  ego_entry->identifier = GNUNET_strdup (identifier);
2379  break;
2380  }
2381  }
2382  if (NULL == ego_entry)
2383  {
2384  /* Add */
2385  ego_entry = GNUNET_new (struct EgoEntry);
2388  ego_entry->ego = ego;
2389  ego_entry->identifier = GNUNET_strdup (identifier);
2391  ego_tail,
2392  ego_entry);
2393  }
2394  }
2395  else
2396  {
2397  /* Delete */
2398  for (ego_entry = ego_head; NULL != ego_entry;
2399  ego_entry = ego_entry->next)
2400  {
2401  if (ego_entry->ego == ego)
2402  break;
2403  }
2404  if (NULL == ego_entry)
2405  return; /* Not found */
2406 
2407  GNUNET_CONTAINER_DLL_remove (ego_head,
2408  ego_tail,
2409  ego_entry);
2410  GNUNET_free (ego_entry->identifier);
2411  GNUNET_free (ego_entry->keystring);
2412  GNUNET_free (ego_entry);
2413  return;
2414  }
2415 }
2416 
2417 
2418 static void
2420  const char *url,
2421  void *cls)
2422 {
2423  json_t *oidc_config;
2424  json_t *auth_methods;
2425  json_t *sig_algs;
2426  json_t *scopes;
2427  json_t *response_types;
2428  json_t *sub_types;
2429  json_t *claim_types;
2430  char *oidc_config_str;
2431  struct MHD_Response *resp;
2432  struct RequestHandle *handle = cls;
2433 
2434  oidc_config = json_object ();
2435  // FIXME get from config?
2436  json_object_set_new (oidc_config,
2437  "issuer", json_string ("http://localhost:7776"));
2438  json_object_set_new (oidc_config,
2439  "authorization_endpoint",
2440  json_string ("https://api.reclaim/openid/authorize"));
2441  json_object_set_new (oidc_config,
2442  "token_endpoint",
2443  json_string ("http://localhost:7776/openid/token"));
2444  auth_methods = json_array ();
2445  json_array_append_new (auth_methods,
2446  json_string ("client_secret_basic"));
2447  json_array_append_new (auth_methods,
2448  json_string ("client_secret_post"));
2449  json_object_set_new (oidc_config,
2450  "token_endpoint_auth_methods_supported",
2451  auth_methods);
2452  sig_algs = json_array ();
2453  json_array_append_new (sig_algs,
2454  json_string ("HS512"));
2455  json_object_set_new (oidc_config,
2456  "id_token_signing_alg_values_supported",
2457  sig_algs);
2458  json_object_set_new (oidc_config,
2459  "userinfo_endpoint",
2460  json_string ("http://localhost:7776/openid/userinfo"));
2461  scopes = json_array ();
2462  json_array_append_new (scopes,
2463  json_string ("openid"));
2464  json_array_append_new (scopes,
2465  json_string ("profile"));
2466  json_array_append_new (scopes,
2467  json_string ("email"));
2468  json_array_append_new (scopes,
2469  json_string ("address"));
2470  json_array_append_new (scopes,
2471  json_string ("phone"));
2472  json_object_set_new (oidc_config,
2473  "scopes_supported",
2474  scopes);
2475  response_types = json_array ();
2476  json_array_append_new (response_types,
2477  json_string ("code"));
2478  json_object_set_new (oidc_config,
2479  "response_types_supported",
2480  response_types);
2481  sub_types = json_array ();
2482  json_array_append_new (sub_types,
2483  json_string ("public")); /* no pairwise suppport */
2484  json_object_set_new (oidc_config,
2485  "subject_types_supported",
2486  sub_types);
2487  claim_types = json_array ();
2488  json_array_append_new (claim_types,
2489  json_string ("normal"));
2490  json_array_append_new (claim_types,
2491  json_string ("aggregated"));
2492  json_object_set_new (oidc_config,
2493  "claim_types_supported",
2494  claim_types);
2495  json_object_set_new (oidc_config,
2496  "claims_parameter_supported",
2497  json_boolean (1));
2498  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2499  resp = GNUNET_REST_create_response (oidc_config_str);
2500  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2501  GNUNET_free (oidc_config_str);
2502  cleanup_handle (handle);
2503 }
2504 
2505 
2513 static void
2515  const char *url,
2516  void *cls)
2517 {
2518  struct MHD_Response *resp;
2519  struct RequestHandle *handle = cls;
2520 
2521  // For now, independent of path return all options
2522  resp = GNUNET_REST_create_response (NULL);
2523  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
2524  MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
2525  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2526  cleanup_handle (handle);
2527  return;
2528 }
2529 
2530 
2531 static enum GNUNET_GenericReturnValue
2534  void *proc_cls)
2535 {
2536  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2538  static const struct GNUNET_REST_RequestHandler handlers[] =
2539  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2540  { MHD_HTTP_METHOD_POST,
2541  GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2542  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2543  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2544  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2545  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2546  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2548  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2549  &oidc_config_cors },
2550  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2552 
2553  handle->oidc = GNUNET_new (struct OIDC_Variables);
2554  if (NULL == OIDC_cookie_jar_map)
2555  OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2556  GNUNET_NO);
2557  handle->response_code = 0;
2559  handle->proc_cls = proc_cls;
2560  handle->proc = proc;
2561  handle->rest_handle = rest_handle;
2562  handle->url = GNUNET_strdup (rest_handle->url);
2563  handle->timeout_task =
2564  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2565  GNUNET_CONTAINER_DLL_insert (requests_head,
2566  requests_tail,
2567  handle);
2568  if (handle->url[strlen (handle->url) - 1] == '/')
2569  handle->url[strlen (handle->url) - 1] = '\0';
2570  if (GNUNET_NO ==
2571  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2572  return GNUNET_NO;
2573 
2574  return GNUNET_YES;
2575 }
2576 
2577 
2584 void *
2586 {
2587  static struct Plugin plugin;
2588  struct GNUNET_REST_Plugin *api;
2589 
2590  cfg = cls;
2591  if (NULL != plugin.cfg)
2592  return NULL; /* can only initialize once! */
2593  memset (&plugin, 0, sizeof(struct Plugin));
2594  plugin.cfg = cfg;
2595  api = GNUNET_new (struct GNUNET_REST_Plugin);
2596  api->cls = &plugin;
2599  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2600  gns_handle = GNUNET_GNS_connect (cfg);
2601  idp = GNUNET_RECLAIM_connect (cfg);
2602 
2605  "%s, %s, %s, %s, %s",
2606  MHD_HTTP_METHOD_GET,
2607  MHD_HTTP_METHOD_POST,
2608  MHD_HTTP_METHOD_PUT,
2609  MHD_HTTP_METHOD_DELETE,
2610  MHD_HTTP_METHOD_OPTIONS);
2611 
2613  _ ("OpenID Connect REST API initialized\n"));
2614  return api;
2615 }
2616 
2617 
2618 static int
2619 cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2620 {
2621  GNUNET_free (value);
2622  return GNUNET_YES;
2623 }
2624 
2625 
2632 void *
2634 {
2635  struct GNUNET_REST_Plugin *api = cls;
2636  struct Plugin *plugin = api->cls;
2637  struct EgoEntry *ego_entry;
2638 
2639  plugin->cfg = NULL;
2640  while (NULL != requests_head)
2641  cleanup_handle (requests_head);
2642  if (NULL != OIDC_cookie_jar_map)
2643  {
2644  GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2645  &cleanup_hashmap,
2646  NULL);
2647  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2648  }
2650  if (NULL != gns_handle)
2651  GNUNET_GNS_disconnect (gns_handle);
2652  if (NULL != identity_handle)
2653  GNUNET_IDENTITY_disconnect (identity_handle);
2654  if (NULL != idp)
2656  while (NULL != (ego_entry = ego_head))
2657  {
2658  GNUNET_CONTAINER_DLL_remove (ego_head,
2659  ego_tail,
2660  ego_entry);
2661  GNUNET_free (ego_entry->identifier);
2662  GNUNET_free (ego_entry->keystring);
2663  GNUNET_free (ego_entry);
2664  }
2665  GNUNET_free (api);
2667  "OpenID Connect REST plugin is finished\n");
2668  return NULL;
2669 }
2670 
2671 
2672 /* end of plugin_rest_openid_connect.c */
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:610
static void build_redirect(void *cls)
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
struct GNUNET_RECLAIM_AttributeList * attr_userinfo_list
Attribute claim list for userinfo.
Connection to the GNS service.
Definition: gns_api.h:35
char * redirect_uri
The OIDC redirect uri.
char * scope
The list of oidc scopes.
void GNUNET_RECLAIM_get_credentials_next(struct GNUNET_RECLAIM_CredentialIterator *ait)
Calls the record processor specified in GNUNET_RECLAIM_get_credentials_start for the next record...
Definition: reclaim_api.c:1487
Handle to the service.
Definition: reclaim_api.c:317
The authorization ticket.
#define OIDC_NONCE_KEY
OIDC nonce key.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2103
struct GNUNET_RECLAIM_Attribute * GNUNET_RECLAIM_attribute_new(const char *attr_name, const struct GNUNET_RECLAIM_Identifier *credential, uint32_t type, const void *data, size_t data_size)
Create a new attribute claim.
static struct GNUNET_GNS_Handle * gns_handle
GNS handle.
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
#define OIDC_CODE_CHALLENGE_KEY
OIDC PKCE code challenge.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS.
Definition: gns_api.c:412
struct GNUNET_RECLAIM_Identifier id
ID.
uint32_t type
Type/Format of Claim.
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint32_t type
Type/Format of Claim.
If a value with the given key exists, replace it.
static struct GNUNET_RECLAIM_AttributeList * attribute_list_merge(struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1509
char * nonce
The OIDC nonce.
void GNUNET_RECLAIM_attribute_list_destroy(struct GNUNET_RECLAIM_AttributeList *attrs)
Destroy claim list.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
void * cls
The closure of the plugin.
static void oidc_cred_collect_finished_cb(void *cls)
size_t data_size
The POST data size.
static int parse_credentials_post_body(struct RequestHandle *handle, char **client_id, char **client_secret)
struct GNUNET_RECLAIM_AttributeIterator * attr_it
Attribute iterator.
const char * name
The name of the attribute.
static int cleanup_hashmap(void *cls, const struct GNUNET_HashCode *key, void *value)
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
struct GNUNET_RECLAIM_Credential * credential
The credential.
static struct RequestHandle * requests_tail
DLL.
#define OIDC_CODE_KEY
OIDC code key.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
#define OIDC_ERROR_KEY_SERVER_ERROR
OIDC error key for generic server errors.
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
struct GNUNET_RECLAIM_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_CredentialResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all credentials for a local identity.
Definition: reclaim_api.c:1440
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *test_key)
size_t data_size
Number of bytes in data.
struct GNUNET_GNS_LookupRequest * gns_op
GNS lookup op.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
#define OIDC_CLAIMS_KEY
OIDC claims key.
struct GNUNET_RECLAIM_CredentialListEntry * list_tail
List tail.
char * key
TLS key.
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Handle to a lookup request.
Definition: gns_api.c:48
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:1104
struct GNUNET_RECLAIM_CredentialListEntry * next
DLL.
#define OIDC_COOKIE_EXPIRATION
OIDC cookie expiration (in seconds)
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
Definition: reclaim_api.c:1089
A private key for an identity as per LSD0001.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct returned by the initialization function of the plugin
struct GNUNET_RECLAIM_PresentationListEntry * list_head
List head.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
helper library for OIDC related functions
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
A list of GNUNET_RECLAIM_Attribute structures.
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1701
size_t data_size
Number of bytes in data.
const void * data
Binary value stored as credential value.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1591
static void tld_iter(void *cls, const char *section, const char *option, const char *value)
Iterate over tlds in config.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
int user_cancelled
User cancelled authorization/login.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_RECLAIM_get_attributes_next(struct GNUNET_RECLAIM_AttributeIterator *it)
Calls the record processor specified in GNUNET_RECLAIM_get_attributes_start for the next record...
Definition: reclaim_api.c:1377
#define OIDC_ERROR_KEY_INVALID_TOKEN
OIDC error key for invalid tokens.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
void * libgnunet_plugin_rest_openid_connect_init(void *cls)
Entry point for the plugin.
static struct RequestHandle * requests_head
DLL.
static int state
The processing state.
Handle for an operation with the service.
Definition: reclaim_api.c:41
int GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL)...
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
void OIDC_build_token_response(const char *access_token, const char *id_token, const struct GNUNET_TIME_Relative *expiration_time, char **token_response)
Build a token response for a token request TODO: Maybe we should add the scope here?
Definition: oidc_helper.c:731
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:652
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void login_redirect(void *cls)
Redirects to login page stored in configuration file.
void * proc_cls
The closure of the result processor.
uint64_t abs_value_us
The actual value.
char * edesc
Error response description.
struct OIDC_Variables * oidc
OIDC variables.
Internal representation of the hash map.
Handle for an operation with the identity service.
Definition: identity_api.c:39
#define GNUNET_REST_HANDLER_END
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
Definition: oidc_helper.c:795
#define OIDC_STATE_KEY
OIDC state key.
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
static struct EgoEntry * ego_tail
Ego list.
The request handle.
#define GNUNET_REST_API_NS_OIDC_CONFIG
OIDC config.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
static char * section
Name of the section.
Definition: gnunet-config.c:33
#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE
OIDC error key for unsupported grants.
The ego list.
char * response_type
The OIDC response type.
#define OIDC_RESPONSE_TYPE_KEY
OIDC response_type key.
static int check_authorization(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *cid)
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
OIDC needed variables.
struct GNUNET_RECLAIM_PresentationList * presentations
Presentations.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
static void oidc_ticket_issue_cb(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_PresentationList *pres)
Issues ticket and redirects to relying party with the authorization code as parameter.
Handle for an ego.
Definition: identity.h:36
Handle for a attribute iterator operation.
Definition: reclaim_api.c:182
static void do_timeout(void *cls)
Task run on timeout, sends error message.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
struct GNUNET_RECLAIM_CredentialList * credentials
Credentials.
static char * value
Value of the record to add/remove.
struct GNUNET_IDENTITY_PublicKey identity
The ticket issuer (= the user)
char * emsg
Error response message.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
static char * attr_name
The attribute.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
const char * url
The url as string.
char * client_id
The OIDC client id of the RP.
Handle for the service.
Definition: identity_api.c:95
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static void oidc_config_cors(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
struct GNUNET_RECLAIM_AttributeListEntry * list_tail
List tail.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
char * name
Plugin name.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_AttributeResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all attributes for a local identity.
Definition: reclaim_api.c:1331
#define OIDC_ERROR_KEY_INVALID_COOKIE
OIDC error key for invalid cookies.
#define OIDC_ERROR_KEY_INVALID_REQUEST
OIDC error key for invalid requests.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
char * tld
The tld for redirect.
static int attr_in_userinfo_request(struct RequestHandle *handle, const char *attr_name)
static void oidc_config_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:759
void GNUNET_RECLAIM_credential_list_destroy(struct GNUNET_RECLAIM_CredentialList *credentials)
Destroy claim list.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
static char * option
Name of the option.
Definition: gnunet-config.c:38
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:442
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
const void * data
Binary value stored as presentation value.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_key_get_public(const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: identity_api.c:175
struct GNUNET_RECLAIM_Identifier id
ID.
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:268
size_t data_size
Number of bytes in data.
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
#define OIDC_CODE_VERIFIER_KEY
OIDC PKCE code verifier.
int GNUNET_REST_handle_request(struct GNUNET_REST_RequestHandle *conn, const struct GNUNET_REST_RequestHandler *handlers, struct GNUNET_REST_RequestHandlerError *err, void *cls)
Definition: rest.c:77
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
A 512-bit hashcode.
int response_code
Response code.
static void login_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Combines an identity with a login time and responds OK to login request.
static int res
static void code_redirect(void *cls)
Checks time and cookie and redirects accordingly.
static char * plugin
Solver plugin name as string.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1978
char * OIDC_generate_id_token(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT from attributes.
Definition: oidc_helper.c:329
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:447
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
const char * data
The POST data.
struct RequestHandle * next
DLL.
char * claims
The OIDC claims.
char * keystring
Public key string.
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:586
A credential presentation.
void GNUNET_RECLAIM_presentation_list_destroy(struct GNUNET_RECLAIM_PresentationList *presentations)
Destroy presentations list.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static void oidc_attr_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
size_t data_size
Number of bytes in data.
#define OIDC_ERROR_KEY_ACCESS_DENIED
OIDC error key for denied access.
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2147
struct GNUNET_RECLAIM_CredentialListEntry * list_head
List head.
const char * name
The name of the credential.
static void userinfo_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to userinfo GET and url-encoded POST request.
static struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
#define OIDC_AUTHORIZATION_HEADER_KEY
OIDC cookie header information key.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
static struct GNUNET_RECLAIM_Identifier credential
Credential ID.
struct RequestHandle * prev
DLL.
struct GNUNET_RECLAIM_CredentialIterator * cred_it
Credential iterator.
#define OIDC_EXPECTED_AUTHORIZATION_SCOPE
OIDC expected scope part while authorizing.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:124
static char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
static void build_authz_response(void *cls)
Iteration over all results finished, build final response.
char * state
The OIDC state.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_REST_API_NS_OIDC
REST root namespace.
static void oidc_cred_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
static void client_redirect(void *cls)
Initiate redirect back to client.
static void authorize_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to authorization GET and url-encoded POST request.
char * identifier
Ego Identifier.
static void do_error(void *cls)
Task run on error, sends error message.
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Record type for reclaim OIDC redirect URIs.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
char * redirect_prefix
The redirect prefix.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_(void)
Return relative time of 1s.
Definition: time.c:183
static char * allow_methods
HTTP methods allows for this plugin.
struct GNUNET_RECLAIM_Ticket ticket
A ticket.
An identity key as per LSD0001.
A list of GNUNET_RECLAIM_Presentation structures.
struct GNUNET_IDENTITY_PublicKey client_pkey
The RP client public key.
static void consume_ticket(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *pres)
Collects claims and stores them in handle.
configuration data
Definition: configuration.c:84
static int attr_in_claims_request(struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)
Handle for a plugin.
Definition: block.c:37
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1398
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
If listing is enabled, prints information about the egos.
static enum GNUNET_GenericReturnValue rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
static void token_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to token url-encoded POST request.
A list of GNUNET_RECLAIM_Credential structures.
char * redirect_suffix
The redirect suffix.
#define OIDC_ERROR_KEY_INVALID_CLIENT
OIDC error key for invalid client.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
struct GNUNET_RECLAIM_Presentation * GNUNET_RECLAIM_presentation_new(uint32_t type, const void *data, size_t data_size)
#define GNUNET_RECLAIM_id_is_equal(a, b)
Handle for a ticket iterator operation.
Definition: reclaim_api.c:119
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
#define GNUNET_log(kind,...)
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_RECLAIM_AttributeList * attr_idtoken_list
Attribute claim list for id_token.
struct GNUNET_IDENTITY_PrivateKey priv_key
Pointer to ego private key.
const void * data
Binary value stored as attribute value.
#define OIDC_SCOPE_KEY
OIDC scope key.
static int attr_in_idtoken_request(struct RequestHandle *handle, const char *attr_name)
struct GNUNET_RECLAIM_Operation * idp_op
Idp Operation.
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition: gns_api.c:314
#define OIDC_GRANT_TYPE_VALUE
OIDC grant_type key.
#define ID_REST_STATE_INIT
State while collecting all egos.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
uint32_t type
Type of Claim.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
struct GNUNET_RECLAIM_PresentationListEntry * list_tail
List tail.
char * code_verifier
The PKCE code_verifier.
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:774
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
struct GNUNET_RECLAIM_Credential * GNUNET_RECLAIM_credential_new(const char *name, uint32_t type, const void *data, size_t data_size)
Create a new credential.
Defaults, look in cache, then in DHT.
Common buffer management functions.
struct EgoEntry * prev
DLL.
struct GNUNET_CONTAINER_MultiHashMap * OIDC_cookie_jar_map
OIDC Hash map that keeps track of issued cookies.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:937
void * libgnunet_plugin_rest_openid_connect_done(void *cls)
Exit point from the plugin.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition: buffer.c:103
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
char * code_challenge
The PKCE code_challenge.
struct EgoEntry * ego_entry
IDENTITY Operation.
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1064
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *iss, const struct GNUNET_IDENTITY_PublicKey *rp, const struct GNUNET_RECLAIM_AttributeList *attrs, GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
Definition: reclaim_api.c:1542
uint32_t data
The data value.
int public_client
Public client.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
struct EgoEntry * next
DLL.
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:302
static struct EgoEntry * ego_head
Ego list.
#define GNUNET_REST_API_NS_USERINFO
UserInfo endpoint.
Handle for a credential iterator operation.
Definition: reclaim_api.c:249
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:972
#define ID_REST_STATE_POST_INIT
Done collecting egos.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static void oidc_attr_collect_finished_cb(void *cls)
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
char * login_identity
The identity chosen by the user to login.
static void do_userinfo_error(void *cls)
Task run on error in userinfo endpoint, sends error header.
static void do_redirect_error(void *cls)
Task run on error, sends error message and redirects.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
char * url
The url.