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 
233 #define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
234  GNUNET_TIME_UNIT_SECONDS,2)
235 
239 static char *OIDC_ignored_parameter_array[] = { "display",
240  "prompt",
241  "ui_locales",
242  "response_mode",
243  "id_token_hint",
244  "login_hint",
245  "acr_values" };
246 
251 
256 
261 
265 static char *allow_methods;
266 
270 static struct EgoEntry *ego_head;
271 
275 static struct EgoEntry *ego_tail;
276 
280 static int state;
281 
286 
291 
295 static struct GNUNET_RECLAIM_Handle *idp;
296 
300 struct Plugin
301 {
302  const struct GNUNET_CONFIGURATION_Handle *cfg;
303 };
304 
309 {
313  struct GNUNET_IDENTITY_PublicKey client_pkey;
314 
318  char *client_id;
319 
324 
328  char *scope;
329 
333  char *state;
334 
338  char *nonce;
339 
343  char *claims;
344 
349 
354 
359 
364 
369 
370 };
371 
375 struct EgoEntry
376 {
380  struct EgoEntry *next;
381 
385  struct EgoEntry *prev;
386 
390  char *identifier;
391 
395  char *keystring;
396 
400  struct GNUNET_IDENTITY_Ego *ego;
401 };
402 
403 
404 struct RequestHandle
405 {
409  struct RequestHandle *next;
410 
414  struct RequestHandle *prev;
415 
419  struct EgoEntry *ego_entry;
420 
424  struct GNUNET_IDENTITY_PrivateKey priv_key;
425 
430 
435 
439  struct GNUNET_REST_RequestHandle *rest_handle;
440 
445 
450 
455 
460 
465 
466 
471 
476 
481 
486 
487 
492 
497 
502 
507 
512 
516  void *proc_cls;
517 
521  char *url;
522 
527 
531  char *tld;
532 
537 
542 
546  char *emsg;
547 
551  char *edesc;
552 
556  int response_code;
557 
562 };
563 
568 
573 
574 
579 static void
581 {
582 
583  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
584  if (NULL != handle->timeout_task)
586  if (NULL != handle->attr_it)
588  if (NULL != handle->cred_it)
590  if (NULL != handle->ticket_it)
592  if (NULL != handle->idp_op)
593  GNUNET_RECLAIM_cancel (handle->idp_op);
594  if (NULL != handle->consume_timeout_op)
596  GNUNET_free (handle->url);
597  GNUNET_free (handle->tld);
598  GNUNET_free (handle->redirect_prefix);
599  GNUNET_free (handle->redirect_suffix);
600  GNUNET_free (handle->emsg);
601  GNUNET_free (handle->edesc);
602  if (NULL != handle->gns_op)
604  if (NULL != handle->oidc)
605  {
606  GNUNET_free (handle->oidc->client_id);
607  GNUNET_free (handle->oidc->login_identity);
608  GNUNET_free (handle->oidc->nonce);
609  GNUNET_free (handle->oidc->redirect_uri);
610  GNUNET_free (handle->oidc->response_type);
611  GNUNET_free (handle->oidc->scope);
612  GNUNET_free (handle->oidc->state);
613  if (NULL != handle->oidc->claims)
614  GNUNET_free (handle->oidc->claims);
615  if (NULL != handle->oidc->code_challenge)
616  GNUNET_free (handle->oidc->code_challenge);
617  GNUNET_free (handle->oidc);
618  }
619  if (NULL!=handle->attr_idtoken_list)
621  if (NULL!=handle->attr_userinfo_list)
623  if (NULL!=handle->credentials)
625  if (NULL!=handle->presentations)
627  GNUNET_CONTAINER_DLL_remove (requests_head,
628  requests_tail,
629  handle);
630  if (NULL != handle->access_token)
631  GNUNET_free (handle->access_token);
632  GNUNET_free (handle);
633 }
634 
635 
641 static void
642 do_error (void *cls)
643 {
644  struct RequestHandle *handle = cls;
645  struct MHD_Response *resp;
646  char *json_error;
647 
648  GNUNET_asprintf (&json_error,
649  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
650  handle->emsg,
651  (NULL != handle->edesc) ? handle->edesc : "",
652  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
653  (NULL != handle->oidc->state) ? handle->oidc->state : "",
654  (NULL != handle->oidc->state) ? "\"" : "");
655  if (0 == handle->response_code)
656  handle->response_code = MHD_HTTP_BAD_REQUEST;
657  resp = GNUNET_REST_create_response (json_error);
658  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
659  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic");
660  MHD_add_response_header (resp,
661  MHD_HTTP_HEADER_CONTENT_TYPE,
662  "application/json");
663  handle->proc (handle->proc_cls, resp, handle->response_code);
664  cleanup_handle (handle);
665  GNUNET_free (json_error);
666 }
667 
668 
675 static void
676 do_userinfo_error (void *cls)
677 {
678  struct RequestHandle *handle = cls;
679  struct MHD_Response *resp;
680  char *error;
681 
683  "Error: %s\n", handle->edesc);
684  GNUNET_asprintf (&error,
685  "error=\"%s\", error_description=\"%s\"",
686  handle->emsg,
687  (NULL != handle->edesc) ? handle->edesc : "");
688  resp = GNUNET_REST_create_response ("");
689  GNUNET_assert (MHD_NO !=
690  MHD_add_response_header (resp,
691  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
692  "Bearer"));
693  handle->proc (handle->proc_cls, resp, handle->response_code);
694  cleanup_handle (handle);
695  GNUNET_free (error);
696 }
697 
698 
704 static void
705 do_redirect_error (void *cls)
706 {
707  struct RequestHandle *handle = cls;
708  struct MHD_Response *resp;
709  char *redirect;
710 
711  GNUNET_asprintf (&redirect,
712  "%s?error=%s&error_description=%s%s%s",
713  handle->oidc->redirect_uri,
714  handle->emsg,
715  handle->edesc,
716  (NULL != handle->oidc->state) ? "&state=" : "",
717  (NULL != handle->oidc->state) ? handle->oidc->state : "");
718  resp = GNUNET_REST_create_response ("");
719  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
720  "Location", redirect));
721  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
722  cleanup_handle (handle);
723  GNUNET_free (redirect);
724 }
725 
726 
732 static void
733 do_timeout (void *cls)
734 {
735  struct RequestHandle *handle = cls;
736 
737  handle->timeout_task = NULL;
738  do_error (handle);
739 }
740 
741 
749 static void
751  const char *url,
752  void *cls)
753 {
754  struct MHD_Response *resp;
755  struct RequestHandle *handle = cls;
756 
757  // For now, independent of path return all options
758  resp = GNUNET_REST_create_response (NULL);
759  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
760  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
761  cleanup_handle (handle);
762  return;
763 }
764 
765 
769 static void
771 {
772  struct GNUNET_HashCode cache_key;
773  char *cookies;
774  struct GNUNET_TIME_Absolute current_time, *relog_time;
775  char delimiter[] = "; ";
776  char *tmp_cookies;
777  char *token;
778  char *value;
779 
780  // gets identity of login try with cookie
782  strlen (OIDC_COOKIE_HEADER_KEY),
783  &cache_key);
786  &cache_key))
787  {
788  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
789  return;
790  }
791  // splits cookies and find 'Identity' cookie
792  tmp_cookies =
794  &cache_key);
795  cookies = GNUNET_strdup (tmp_cookies);
796  token = strtok (cookies, delimiter);
797  handle->oidc->user_cancelled = GNUNET_NO;
798  handle->oidc->login_identity = NULL;
799  if (NULL == token)
800  {
802  "Unable to parse cookie: %s\n",
803  cookies);
804  GNUNET_free (cookies);
805  return;
806  }
807 
808  while (NULL != token)
809  {
810  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
811  {
812  handle->oidc->user_cancelled = GNUNET_YES;
813  GNUNET_free (cookies);
814  return;
815  }
816  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
817  break;
818  token = strtok (NULL, delimiter);
819  }
820  if (NULL == token)
821  {
823  "No cookie value to process: %s\n",
824  cookies);
825  GNUNET_free (cookies);
826  return;
827  }
828  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
829  if (GNUNET_NO ==
830  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
831  {
832  GNUNET_log (
834  "Found cookie `%s', but no corresponding expiration entry present...\n",
835  token);
836  GNUNET_free (cookies);
837  return;
838  }
839  relog_time =
840  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
841  current_time = GNUNET_TIME_absolute_get ();
842  // 30 min after old login -> redirect to login
843  if (current_time.abs_value_us > relog_time->abs_value_us)
844  {
846  "Found cookie `%s', but it is expired.\n",
847  token);
848  GNUNET_free (cookies);
849  return;
850  }
851  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
852  GNUNET_assert (NULL != value);
853  handle->oidc->login_identity = GNUNET_strdup (value);
854  GNUNET_free (cookies);
855 }
856 
857 
861 static void
862 login_redirect (void *cls)
863 {
864  char *login_base_url;
865  char *new_redirect;
866  char *tmp;
867  struct MHD_Response *resp;
868  struct GNUNET_Buffer buf = { 0 };
869  struct RequestHandle *handle = cls;
870 
872  "reclaim-rest-plugin",
873  "address",
874  &login_base_url))
875  {
876  GNUNET_buffer_write_str (&buf, login_base_url);
878  "?%s=%s",
880  handle->oidc->response_type);
882  "&%s=%s",
884  handle->oidc->client_id);
886  strlen (handle->oidc->redirect_uri),
887  &tmp);
889  "&%s=%s",
891  tmp);
892  GNUNET_free (tmp);
894  strlen (handle->oidc->scope),
895  &tmp);
897  "&%s=%s",
899  tmp);
900  GNUNET_free (tmp);
901  if (NULL != handle->oidc->state)
902  {
904  strlen (handle->oidc->state),
905  &tmp);
907  "&%s=%s",
909  handle->oidc->state);
910  GNUNET_free (tmp);
911  }
912  if (NULL != handle->oidc->code_challenge)
913  {
915  "&%s=%s",
917  handle->oidc->code_challenge);
918  }
919  if (NULL != handle->oidc->nonce)
920  {
922  "&%s=%s",
924  handle->oidc->nonce);
925  }
926  if (NULL != handle->oidc->claims)
927  {
929  strlen (handle->oidc->claims),
930  &tmp);
932  "&%s=%s",
934  tmp);
935  GNUNET_free (tmp);
936  }
937  new_redirect = GNUNET_buffer_reap_str (&buf);
938  resp = GNUNET_REST_create_response ("");
939  MHD_add_response_header (resp, "Location", new_redirect);
940  GNUNET_free (login_base_url);
941  }
942  else
943  {
945  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
946  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
948  return;
949  }
950  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
951  GNUNET_free (new_redirect);
952  cleanup_handle (handle);
953 }
954 
955 
959 static void
961 {
962  struct RequestHandle *handle = cls;
963 
965  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
967 }
968 
969 
974 static void
976  const struct GNUNET_RECLAIM_Ticket *ticket,
977  const struct
978  GNUNET_RECLAIM_PresentationList *presentation)
979 {
980  struct RequestHandle *handle = cls;
981  struct MHD_Response *resp;
982  char *ticket_str;
983  char *redirect_uri;
984  char *code_string;
985 
986  handle->idp_op = NULL;
987  if (NULL == ticket)
988  {
990  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
992  return;
993  }
994  handle->ticket = *ticket;
995  ticket_str =
997  sizeof(struct GNUNET_RECLAIM_Ticket));
998  code_string = OIDC_build_authz_code (&handle->priv_key,
999  &handle->ticket,
1000  handle->attr_idtoken_list,
1001  presentation,
1002  handle->oidc->nonce,
1003  handle->oidc->code_challenge);
1004  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1005  (NULL != handle->tld))
1006  {
1007  GNUNET_asprintf (&redirect_uri,
1008  "%s.%s/%s%s%s=%s&state=%s",
1009  handle->redirect_prefix,
1010  handle->tld,
1011  handle->redirect_suffix,
1012  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1013  "&"),
1014  handle->oidc->response_type,
1015  code_string,
1016  handle->oidc->state);
1017  }
1018  else
1019  {
1020  GNUNET_asprintf (&redirect_uri,
1021  "%s%s%s=%s&state=%s",
1022  handle->oidc->redirect_uri,
1023  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1024  "&"),
1025  handle->oidc->response_type,
1026  code_string,
1027  handle->oidc->state);
1028  }
1029  resp = GNUNET_REST_create_response ("");
1030  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1031  "Location", redirect_uri));
1032  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1033  cleanup_handle (handle);
1034  GNUNET_free (redirect_uri);
1035  GNUNET_free (ticket_str);
1036  GNUNET_free (code_string);
1037 }
1038 
1039 
1040 static struct GNUNET_RECLAIM_AttributeList*
1042  struct GNUNET_RECLAIM_AttributeList *list_b)
1043 {
1044  struct GNUNET_RECLAIM_AttributeList *merged_list;
1045  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1046  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1047  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1048 
1049  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1050  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1051  {
1054  &le_a->attribute->
1055  credential,
1056  le_a->attribute->type,
1057  le_a->attribute->data,
1058  le_a->attribute->data_size);
1059  le_m->attribute->id = le_a->attribute->id;
1060  le_m->attribute->flag = le_a->attribute->flag;
1061  le_m->attribute->credential = le_a->attribute->credential;
1062  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1063  merged_list->list_tail,
1064  le_m);
1065  }
1066  le_m = NULL;
1067  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1068  {
1069  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1070  {
1072  &le_b->attribute->id))
1073  break;
1074  }
1075  if (NULL != le_m)
1076  continue;
1079  &le_b->attribute->
1080  credential,
1081  le_b->attribute->type,
1082  le_b->attribute->data,
1083  le_b->attribute->data_size);
1084  le_m->attribute->id = le_b->attribute->id;
1085  le_m->attribute->flag = le_b->attribute->flag;
1086  le_m->attribute->credential = le_b->attribute->credential;
1087  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1088  merged_list->list_tail,
1089  le_m);
1090  }
1091  return merged_list;
1092 }
1093 
1094 
1095 static void
1097 {
1098  struct RequestHandle *handle = cls;
1099  struct GNUNET_RECLAIM_AttributeList *merged_list;
1100  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1101 
1102  handle->cred_it = NULL;
1103  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1104  handle->attr_userinfo_list);
1105  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1107  "List Attribute in ticket to issue: %s\n",
1108  le_m->attribute->name);
1109  handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1110  &handle->priv_key,
1111  &handle->oidc->client_pkey,
1112  merged_list,
1114  handle);
1116 }
1117 
1118 
1122 static void
1124  const struct GNUNET_IDENTITY_PublicKey *identity,
1125  const struct GNUNET_RECLAIM_Credential *cred)
1126 {
1127  struct RequestHandle *handle = cls;
1130 
1131  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1132  {
1134  &cred->id))
1135  continue;
1138  return;
1139  }
1140 
1141  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1142  {
1144  &cred->id))
1145  continue;
1149  cred->type,
1150  cred->data,
1151  cred->data_size);
1153  handle->credentials->list_tail,
1154  ale);
1155  }
1157 }
1158 
1159 
1160 static void
1162 {
1163  struct RequestHandle *handle = cls;
1164 
1165  handle->attr_it = NULL;
1166  handle->ticket_it = NULL;
1167  if (NULL == handle->attr_idtoken_list->list_head)
1168  {
1170  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1172  return;
1173  }
1175  handle->cred_it =
1177  &handle->priv_key,
1179  handle,
1181  handle,
1183  handle);
1184 
1185 }
1186 
1187 
1188 static int
1190  const char *attr_name,
1191  const char *claims_parameter)
1192 {
1193  int ret = GNUNET_NO;
1194  json_t *root;
1195  json_error_t error;
1196  json_t *claims_j;
1197  const char *key;
1198  json_t *value;
1199 
1202  attr_name))
1203  return GNUNET_YES;
1204 
1206  if (NULL != handle->oidc->claims)
1207  {
1208  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1209  claims_j = json_object_get (root, claims_parameter);
1210  /* obj is a JSON object */
1211  if (NULL != claims_j)
1212  {
1213  json_object_foreach (claims_j, key, value) {
1214  if (0 != strcmp (attr_name, key))
1215  continue;
1216  ret = GNUNET_YES;
1217  break;
1218  }
1219  }
1220  json_decref (root);
1221  }
1222  return ret;
1223 }
1224 
1225 
1226 static int
1228  const char *attr_name)
1229 {
1230  return attr_in_claims_request (handle, attr_name, "id_token");
1231 }
1232 
1233 
1234 static int
1236  const char *attr_name)
1237 {
1238  return attr_in_claims_request (handle, attr_name, "userinfo");
1239 }
1240 
1241 
1245 static void
1247  const struct GNUNET_IDENTITY_PublicKey *identity,
1248  const struct GNUNET_RECLAIM_Attribute *attr)
1249 {
1250  struct RequestHandle *handle = cls;
1252  if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1253  {
1256  &attr->credential,
1257  attr->type,
1258  attr->data,
1259  attr->data_size);
1260  le->attribute->id = attr->id;
1261  le->attribute->flag = attr->flag;
1262  le->attribute->credential = attr->credential;
1264  handle->attr_idtoken_list->list_tail,
1265  le);
1266  }
1267  if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1268  {
1271  &attr->credential,
1272  attr->type,
1273  attr->data,
1274  attr->data_size);
1275  le->attribute->id = attr->id;
1276  le->attribute->flag = attr->flag;
1277  le->attribute->credential = attr->credential;
1279  handle->attr_userinfo_list->list_tail,
1280  le);
1281  }
1282 
1284 }
1285 
1286 
1290 static void
1291 code_redirect (void *cls)
1292 {
1293  struct RequestHandle *handle = cls;
1294  struct GNUNET_TIME_Absolute current_time;
1295  struct GNUNET_TIME_Absolute *relog_time;
1296  struct GNUNET_IDENTITY_PublicKey pubkey;
1297  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1298  struct GNUNET_HashCode cache_key;
1299  char *identity_cookie;
1300 
1301  GNUNET_asprintf (&identity_cookie,
1302  "Identity=%s",
1303  handle->oidc->login_identity);
1304  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1305  GNUNET_free (identity_cookie);
1306  // No login time for identity -> redirect to login
1307  if (GNUNET_YES ==
1308  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1309  {
1310  relog_time =
1311  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1312  current_time = GNUNET_TIME_absolute_get ();
1313  // 30 min after old login -> redirect to login
1314  if (current_time.abs_value_us <= relog_time->abs_value_us)
1315  {
1316  if (GNUNET_OK !=
1318  ->login_identity,
1319  &pubkey))
1320  {
1322  handle->edesc =
1323  GNUNET_strdup ("The cookie of a login identity is not valid");
1325  return;
1326  }
1327  // iterate over egos and compare their public key
1328  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1329  handle->ego_entry = handle->ego_entry->next)
1330  {
1331  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1332  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1333  {
1334  handle->priv_key =
1336  handle->attr_idtoken_list =
1338  handle->attr_userinfo_list =
1340  handle->attr_it =
1342  &handle->priv_key,
1344  handle,
1346  handle,
1348  handle);
1349  return;
1350  }
1351  }
1353  return;
1354  }
1355  }
1356 }
1357 
1358 
1359 static void
1360 build_redirect (void *cls)
1361 {
1362  struct RequestHandle *handle = cls;
1363  struct MHD_Response *resp;
1364  char *redirect_uri;
1365 
1366  if (GNUNET_YES == handle->oidc->user_cancelled)
1367  {
1368  if ((NULL != handle->redirect_prefix) &&
1369  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1370  {
1371  GNUNET_asprintf (&redirect_uri,
1372  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1373  handle->redirect_prefix,
1374  handle->tld,
1375  handle->redirect_suffix,
1376  "access_denied",
1377  "User denied access",
1378  handle->oidc->state);
1379  }
1380  else
1381  {
1382  GNUNET_asprintf (&redirect_uri,
1383  "%s?error=%s&error_description=%s&state=%s",
1384  handle->oidc->redirect_uri,
1385  "access_denied",
1386  "User denied access",
1387  handle->oidc->state);
1388  }
1389  resp = GNUNET_REST_create_response ("");
1390  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1391  "Location",
1392  redirect_uri));
1393  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1394  cleanup_handle (handle);
1395  GNUNET_free (redirect_uri);
1396  return;
1397  }
1399 }
1400 
1401 
1402 static void
1404  uint32_t rd_count,
1405  const struct GNUNET_GNSRECORD_Data *rd)
1406 {
1407  struct RequestHandle *handle = cls;
1408  char *tmp;
1409  char *tmp_key_str;
1410  char *pos;
1411  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1412 
1413  handle->gns_op = NULL;
1414  if (0 == rd_count)
1415  {
1417  handle->edesc =
1418  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1420  return;
1421  }
1422  for (int i = 0; i < rd_count; i++)
1423  {
1424  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1425  continue;
1426  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1427  continue;
1428  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1429  if (NULL == strstr (tmp, handle->oidc->client_id))
1430  {
1432  "Redirect uri %s does not contain client_id %s\n",
1433  tmp,
1434  handle->oidc->client_id);
1435  }
1436  else
1437  {
1438  pos = strrchr (tmp, (unsigned char) '.');
1439  if (NULL == pos)
1440  {
1442  "Redirect uri %s contains client_id but is malformed\n",
1443  tmp);
1444  GNUNET_free (tmp);
1445  continue;
1446  }
1447  *pos = '\0';
1448  handle->redirect_prefix = GNUNET_strdup (tmp);
1449  tmp_key_str = pos + 1;
1450  pos = strchr (tmp_key_str, (unsigned char) '/');
1451  if (NULL == pos)
1452  {
1454  "Redirect uri %s contains client_id but is malformed\n",
1455  tmp);
1456  GNUNET_free (tmp);
1457  continue;
1458  }
1459  *pos = '\0';
1460  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1461 
1462  GNUNET_STRINGS_string_to_data (tmp_key_str,
1463  strlen (tmp_key_str),
1464  &redirect_zone,
1465  sizeof(redirect_zone));
1466  }
1468  GNUNET_free (tmp);
1469  return;
1470  }
1472  handle->edesc =
1473  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1475 }
1476 
1477 
1481 static void
1482 client_redirect (void *cls)
1483 {
1484  struct RequestHandle *handle = cls;
1485 
1486  /* Lookup client redirect uri to verify request */
1487  handle->gns_op =
1488  GNUNET_GNS_lookup (gns_handle,
1490  &handle->oidc->client_pkey,
1494  handle);
1495 }
1496 
1497 
1498 static char *
1499 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1500 {
1501  struct GNUNET_HashCode hc;
1502  char *value;
1503  char *res;
1504 
1505  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1507  ->url_param_map,
1508  &hc))
1509  return NULL;
1510  value =
1512  if (NULL == value)
1513  return NULL;
1514  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1515  return res;
1516 }
1517 
1518 
1525 static void
1527 {
1528  struct RequestHandle *handle = cls;
1529  struct GNUNET_HashCode cache_key;
1530 
1531  char *expected_scope;
1532  char delimiter[] = " ";
1533  int number_of_ignored_parameter, iterator;
1534 
1535 
1536  // REQUIRED value: redirect_uri
1537  handle->oidc->redirect_uri =
1539  if (NULL == handle->oidc->redirect_uri)
1540  {
1542  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1544  return;
1545  }
1546 
1547  // REQUIRED value: response_type
1548  handle->oidc->response_type =
1550  if (NULL == handle->oidc->response_type)
1551  {
1553  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1555  return;
1556  }
1557 
1558  // REQUIRED value: scope
1559  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1560  if (NULL == handle->oidc->scope)
1561  {
1563  handle->edesc = GNUNET_strdup ("missing parameter scope");
1565  return;
1566  }
1567 
1568  // OPTIONAL value: nonce
1569  handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1570 
1571  // OPTIONAL value: claims
1572  handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1573 
1574  // TODO check other values if needed
1575  number_of_ignored_parameter =
1576  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1577  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1578  {
1580  strlen (OIDC_ignored_parameter_array[iterator]),
1581  &cache_key);
1582  if (GNUNET_YES ==
1584  ->url_param_map,
1585  &cache_key))
1586  {
1588  GNUNET_asprintf (&handle->edesc,
1589  "Server will not handle parameter: %s",
1590  OIDC_ignored_parameter_array[iterator]);
1592  return;
1593  }
1594  }
1595 
1596  // We only support authorization code flows.
1597  if (0 != strcmp (handle->oidc->response_type,
1599  {
1601  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1602  "obtaining this authorization code.");
1604  return;
1605  }
1606 
1607  // Checks if scope contains 'openid'
1608  expected_scope = GNUNET_strdup (handle->oidc->scope);
1609  char *test;
1610  test = strtok (expected_scope, delimiter);
1611  while (NULL != test)
1612  {
1613  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1614  break;
1615  test = strtok (NULL, delimiter);
1616  }
1617  if (NULL == test)
1618  {
1620  handle->edesc =
1621  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1623  GNUNET_free (expected_scope);
1624  return;
1625  }
1626 
1627  GNUNET_free (expected_scope);
1628  if ((NULL == handle->oidc->login_identity) &&
1629  (GNUNET_NO == handle->oidc->user_cancelled))
1631  else
1633 }
1634 
1635 
1639 static void
1640 tld_iter (void *cls, const char *section, const char *option, const char *value)
1641 {
1642  struct RequestHandle *handle = cls;
1643  struct GNUNET_IDENTITY_PublicKey pkey;
1644 
1645  if (GNUNET_OK !=
1647  {
1648  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1649  return;
1650  }
1651  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1652  handle->tld = GNUNET_strdup (option + 1);
1653 }
1654 
1655 
1663 static void
1665  const char *url,
1666  void *cls)
1667 {
1668  struct RequestHandle *handle = cls;
1669  struct EgoEntry *tmp_ego;
1670  const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1671  struct GNUNET_IDENTITY_PublicKey pkey;
1672 
1674 
1675  // RECOMMENDED value: state - REQUIRED for answers
1676  handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1677 
1678  // REQUIRED value: client_id
1680  if (NULL == handle->oidc->client_id)
1681  {
1683  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1684  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1686  return;
1687  }
1688 
1689  // OPTIONAL value: code_challenge
1690  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1692  if (NULL == handle->oidc->code_challenge)
1693  {
1695  "OAuth authorization request does not contain PKCE parameters!\n");
1696  }
1697 
1698  if (GNUNET_OK !=
1700  &handle->oidc->client_pkey))
1701  {
1703  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1704  "authorization code using this method.");
1705  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1707  return;
1708  }
1709 
1710  // If we know this identity, translated the corresponding TLD
1711  // TODO: We might want to have a reverse lookup functionality for TLDs?
1712  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1713  {
1714  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1715  GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1716  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1717  {
1718  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1719  handle->ego_entry = ego_tail;
1720  }
1721  }
1722  if (NULL == handle->tld)
1724  if (NULL == handle->tld)
1725  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1727 }
1728 
1729 
1737 static void
1739  const char *url,
1740  void *cls)
1741 {
1742  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1743  struct RequestHandle *handle = cls;
1744  struct GNUNET_HashCode cache_key;
1745  struct GNUNET_TIME_Absolute *current_time;
1746  struct GNUNET_TIME_Absolute *last_time;
1747  char *cookie;
1748  char *header_val;
1749  json_t *root;
1750  json_error_t error;
1751  json_t *identity;
1752  char term_data[handle->rest_handle->data_size + 1];
1753 
1754  term_data[handle->rest_handle->data_size] = '\0';
1755  GNUNET_memcpy (term_data,
1756  handle->rest_handle->data,
1757  handle->rest_handle->data_size);
1758  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1759  identity = json_object_get (root, "identity");
1760  if (! json_is_string (identity))
1761  {
1763  "Error parsing json string from %s\n",
1764  term_data);
1765  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1766  json_decref (root);
1767  cleanup_handle (handle);
1768  return;
1769  }
1770  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1771  GNUNET_asprintf (&header_val,
1772  "%s;Max-Age=%d",
1773  cookie,
1775  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1776  "Set-Cookie", header_val));
1777  GNUNET_assert (MHD_NO !=
1778  MHD_add_response_header (resp,
1779  "Access-Control-Allow-Methods",
1780  "POST"));
1781  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1782 
1783  if (0 != strcmp (json_string_value (identity), "Denied"))
1784  {
1785  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1786  *current_time = GNUNET_TIME_relative_to_absolute (
1789  last_time =
1790  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1791  GNUNET_free (last_time);
1792  GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1793  &cache_key,
1794  current_time,
1796  }
1797  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1798  GNUNET_free (cookie);
1799  GNUNET_free (header_val);
1800  json_decref (root);
1801  cleanup_handle (handle);
1802 }
1803 
1804 
1805 static int
1807  char **client_id,
1808  char **client_secret)
1809 {
1810  struct GNUNET_HashCode cache_key;
1811  char *authorization;
1812  char *credentials;
1813  char *basic_authorization;
1814  char *client_id_tmp;
1815  char *pass;
1816 
1819  &cache_key);
1821  ->header_param_map,
1822  &cache_key))
1823  return GNUNET_SYSERR;
1824  authorization =
1826  &cache_key);
1827 
1828  // split header in "Basic" and [content]
1829  credentials = strtok (authorization, " ");
1830  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1831  return GNUNET_SYSERR;
1832  credentials = strtok (NULL, " ");
1833  if (NULL == credentials)
1834  return GNUNET_SYSERR;
1835  GNUNET_STRINGS_base64_decode (credentials,
1836  strlen (credentials),
1837  (void **) &basic_authorization);
1838 
1839  if (NULL == basic_authorization)
1840  return GNUNET_SYSERR;
1841  client_id_tmp = strtok (basic_authorization, ":");
1842  if (NULL == client_id_tmp)
1843  {
1844  GNUNET_free (basic_authorization);
1845  return GNUNET_SYSERR;
1846  }
1847  pass = strtok (NULL, ":");
1848  if (NULL == pass)
1849  {
1850  GNUNET_free (basic_authorization);
1851  return GNUNET_SYSERR;
1852  }
1853  *client_id = strdup (client_id_tmp);
1854  *client_secret = strdup (pass);
1855  GNUNET_free (basic_authorization);
1856  return GNUNET_OK;
1857 }
1858 
1859 
1860 static int
1862  char **client_id,
1863  char **client_secret)
1864 {
1865  struct GNUNET_HashCode cache_key;
1866  char *client_id_tmp;
1867  char *pass;
1868 
1869  GNUNET_CRYPTO_hash ("client_id",
1870  strlen ("client_id"),
1871  &cache_key);
1873  ->url_param_map,
1874  &cache_key))
1875  return GNUNET_SYSERR;
1876  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1877  handle->rest_handle->url_param_map,
1878  &cache_key);
1879  if (NULL == client_id_tmp)
1880  return GNUNET_SYSERR;
1881  *client_id = strdup (client_id_tmp);
1882  GNUNET_CRYPTO_hash ("client_secret",
1883  strlen ("client_secret"),
1884  &cache_key);
1886  ->url_param_map,
1887  &cache_key))
1888  {
1889  GNUNET_free (*client_id);
1890  *client_id = NULL;
1891  return GNUNET_SYSERR;
1892  }
1894  &cache_key);
1895  if (NULL == pass)
1896  {
1897  GNUNET_free (*client_id);
1898  *client_id = NULL;
1899  return GNUNET_SYSERR;
1900  }
1901  *client_secret = strdup (pass);
1902  return GNUNET_OK;
1903 }
1904 
1905 
1906 static int
1908  struct GNUNET_IDENTITY_PublicKey *cid)
1909 {
1910  char *expected_pass;
1911  char *received_cid;
1912  char *received_cpw;
1913  char *pkce_cv;
1914 
1915  if (GNUNET_OK == parse_credentials_basic_auth (handle,
1916  &received_cid,
1917  &received_cpw))
1918  {
1920  "Received client credentials in HTTP AuthZ header\n");
1921  }
1922  else if (GNUNET_OK == parse_credentials_post_body (handle,
1923  &received_cid,
1924  &received_cpw))
1925  {
1927  "Received client credentials in POST body\n");
1928  }
1929  else
1930  {
1932  pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1933  if (NULL == pkce_cv)
1934  {
1936  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1937  return GNUNET_SYSERR;
1938  }
1939  handle->public_client = GNUNET_YES;
1940  GNUNET_free (pkce_cv);
1941  received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1942  GNUNET_STRINGS_string_to_data (received_cid,
1943  strlen (received_cid),
1944  cid,
1945  sizeof(struct GNUNET_IDENTITY_PublicKey));
1946  GNUNET_free (received_cid);
1947  return GNUNET_OK;
1948 
1949  }
1950 
1951  // check client password
1953  "reclaim-rest-plugin",
1954  "OIDC_CLIENT_SECRET",
1955  &expected_pass))
1956  {
1957  if (0 != strcmp (expected_pass, received_cpw))
1958  {
1959  GNUNET_free (expected_pass);
1961  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1962  GNUNET_free (received_cpw);
1963  GNUNET_free (received_cid);
1964  return GNUNET_SYSERR;
1965  }
1966  GNUNET_free (expected_pass);
1967  }
1968  else
1969  {
1970  GNUNET_free (received_cpw);
1971  GNUNET_free (received_cid);
1973  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1974  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1975  return GNUNET_SYSERR;
1976  }
1977  // check client_id
1978  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1979  handle->ego_entry = handle->ego_entry->next)
1980  {
1981  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1982  break;
1983  }
1984  if (NULL == handle->ego_entry)
1985  {
1986  GNUNET_free (received_cpw);
1987  GNUNET_free (received_cid);
1989  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1990  return GNUNET_SYSERR;
1991  }
1992  GNUNET_STRINGS_string_to_data (received_cid,
1993  strlen (received_cid),
1994  cid,
1995  sizeof(struct GNUNET_IDENTITY_PublicKey));
1996 
1997  GNUNET_free (received_cpw);
1998  GNUNET_free (received_cid);
1999  return GNUNET_OK;
2000 }
2001 
2002 
2003 const struct EgoEntry *
2005  struct GNUNET_IDENTITY_PublicKey *test_key)
2006 {
2007  struct EgoEntry *ego_entry;
2008  struct GNUNET_IDENTITY_PublicKey pub_key;
2009 
2010  for (ego_entry = ego_head; NULL != ego_entry;
2011  ego_entry = ego_entry->next)
2012  {
2013  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2014  if (0 == GNUNET_memcmp (&pub_key, test_key))
2015  return ego_entry;
2016  }
2017  return NULL;
2018 }
2019 
2020 
2028 static void
2030  const char *url,
2031  void *cls)
2032 {
2033  struct RequestHandle *handle = cls;
2034  const struct EgoEntry *ego_entry;
2035  struct GNUNET_TIME_Relative expiration_time;
2036  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2037  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2038  struct GNUNET_RECLAIM_Ticket ticket;
2039  struct GNUNET_IDENTITY_PublicKey cid;
2040  struct GNUNET_HashCode cache_key;
2041  struct MHD_Response *resp;
2042  char *grant_type;
2043  char *code;
2044  char *json_response;
2045  char *id_token;
2046  char *access_token;
2047  char *jwt_secret;
2048  char *nonce = NULL;
2049  char *code_verifier;
2050 
2051  /*
2052  * Check Authorization
2053  */
2054  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2055  {
2057  "OIDC authorization for token endpoint failed\n");
2059  return;
2060  }
2061 
2062  /*
2063  * Check parameter
2064  */
2065 
2066  // TODO Do not allow multiple equal parameter names
2067  // REQUIRED grant_type
2069  strlen (OIDC_GRANT_TYPE_KEY),
2070  &cache_key);
2071  grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2072  if (NULL == grant_type)
2073  {
2075  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2076  handle->response_code = MHD_HTTP_BAD_REQUEST;
2078  return;
2079  }
2080 
2081  // Check parameter grant_type == "authorization_code"
2082  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2083  {
2085  handle->response_code = MHD_HTTP_BAD_REQUEST;
2086  GNUNET_free (grant_type);
2088  return;
2089  }
2090  GNUNET_free (grant_type);
2091  // REQUIRED code
2092  code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2093  if (NULL == code)
2094  {
2096  handle->edesc = GNUNET_strdup ("missing parameter code");
2097  handle->response_code = MHD_HTTP_BAD_REQUEST;
2099  return;
2100  }
2101  ego_entry = find_ego (handle, &cid);
2102  if (NULL == ego_entry)
2103  {
2105  handle->edesc = GNUNET_strdup ("Unknown client");
2106  handle->response_code = MHD_HTTP_BAD_REQUEST;
2107  GNUNET_free (code);
2109  return;
2110  }
2111 
2112  // REQUIRED code verifier
2113  code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2114  if (NULL == code_verifier)
2115  {
2117  "OAuth authorization request does not contain PKCE parameters!\n");
2118 
2119  }
2120 
2121  // decode code
2122  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2123  &cl, &pl, &nonce,
2125  {
2127  handle->edesc = GNUNET_strdup ("invalid code");
2128  handle->response_code = MHD_HTTP_BAD_REQUEST;
2129  GNUNET_free (code);
2130  if (NULL != code_verifier)
2131  GNUNET_free (code_verifier);
2133  return;
2134  }
2135  if (NULL != code_verifier)
2136  GNUNET_free (code_verifier);
2137 
2138  // create jwt
2140  "reclaim-rest-plugin",
2141  "expiration_time",
2142  &expiration_time))
2143  {
2145  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2146  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2147  GNUNET_free (code);
2148  if (NULL != nonce)
2149  GNUNET_free (nonce);
2153  return;
2154  }
2155 
2156 
2157  // TODO OPTIONAL acr,amr,azp
2159  "reclaim-rest-plugin",
2160  "jwt_secret",
2161  &jwt_secret))
2162  {
2164  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2165  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2166  GNUNET_free (code);
2169  if (NULL != nonce)
2170  GNUNET_free (nonce);
2172  return;
2173  }
2174  id_token = OIDC_generate_id_token (&ticket.audience,
2175  &ticket.identity,
2176  cl,
2177  pl,
2178  &expiration_time,
2179  (NULL != nonce) ? nonce : NULL,
2180  jwt_secret);
2181  GNUNET_free (jwt_secret);
2182  if (NULL != nonce)
2183  GNUNET_free (nonce);
2184  access_token = OIDC_access_token_new (&ticket);
2185  /* Store mapping from access token to code so we can later
2186  * fall back on the provided attributes in userinfo
2187  */
2188  GNUNET_CRYPTO_hash (access_token,
2189  strlen (access_token),
2190  &cache_key);
2191  char *tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2192  &cache_key);
2193  GNUNET_CONTAINER_multihashmap_put (oidc_code_cache,
2194  &cache_key,
2195  code,
2197  /* If there was a previous code in there, free the old value */
2198  if (NULL != tmp_at)
2199  {
2201  "OIDC access token already issued. Cleanup.\n");
2202  GNUNET_free (tmp_at);
2203  }
2204 
2205  OIDC_build_token_response (access_token,
2206  id_token,
2207  &expiration_time,
2208  &json_response);
2209 
2210  resp = GNUNET_REST_create_response (json_response);
2211  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2212  "Cache-Control",
2213  "no-store"));
2214  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2215  "Pragma", "no-cache"));
2216  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2217  "Content-Type",
2218  "application/json"));
2219  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2222  GNUNET_free (access_token);
2223  GNUNET_free (json_response);
2224  GNUNET_free (id_token);
2225  cleanup_handle (handle);
2226 }
2227 
2228 
2232 static void
2233 consume_ticket (void *cls,
2234  const struct GNUNET_IDENTITY_PublicKey *identity,
2235  const struct GNUNET_RECLAIM_Attribute *attr,
2236  const struct GNUNET_RECLAIM_Presentation *presentation)
2237 {
2238  struct RequestHandle *handle = cls;
2241  struct MHD_Response *resp;
2242  char *result_str;
2243 
2244  if (NULL != handle->consume_timeout_op)
2246  handle->consume_timeout_op = NULL;
2247  handle->idp_op = NULL;
2248 
2249  if (NULL == identity)
2250  {
2251  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2252  handle->attr_userinfo_list,
2253  handle->presentations);
2254  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2255  resp = GNUNET_REST_create_response (result_str);
2256  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2257  GNUNET_free (result_str);
2258  cleanup_handle (handle);
2259  return;
2260  }
2263  &attr->credential,
2264  attr->type,
2265  attr->data,
2266  attr->data_size);
2267  ale->attribute->id = attr->id;
2268  ale->attribute->flag = attr->flag;
2269  ale->attribute->credential = attr->credential;
2271  handle->attr_userinfo_list->list_tail,
2272  ale);
2273  if (NULL == presentation)
2274  return;
2275  for (atle = handle->presentations->list_head;
2276  NULL != atle; atle = atle->next)
2277  {
2279  &atle->presentation->credential_id,
2280  &presentation->credential_id))
2281  continue;
2282  break;
2283  }
2284  if (NULL == atle)
2285  {
2288  atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2289  presentation->data,
2290  presentation->
2291  data_size);
2292  atle->presentation->credential_id = presentation->credential_id;
2294  handle->presentations->list_tail,
2295  atle);
2296  }
2297 }
2298 
2299 
2300 static void
2302 {
2303  struct RequestHandle *handle = cls;
2304  struct GNUNET_HashCode cache_key;
2305  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2306  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2307  struct GNUNET_RECLAIM_Ticket ticket;
2308  char *nonce;
2309  char *cached_code;
2310 
2311  handle->consume_timeout_op = NULL;
2312  if (NULL != handle->idp_op)
2313  GNUNET_RECLAIM_cancel (handle->idp_op);
2314  handle->idp_op = NULL;
2315 
2317  "Ticket consumptioned timed out. Using cache...\n");
2319  strlen (handle->access_token),
2320  &cache_key);
2321  cached_code = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2322  &cache_key);
2323  if (NULL == cached_code)
2324  {
2326  handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2327  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2329  return;
2330  }
2331 
2332  // decode code
2334  cached_code, NULL, &ticket,
2335  &cl, &pl, &nonce,
2337  {
2339  handle->edesc = GNUNET_strdup ("invalid code");
2340  handle->response_code = MHD_HTTP_BAD_REQUEST;
2341  GNUNET_free (cached_code);
2342  if (NULL != nonce)
2343  GNUNET_free (nonce);
2345  return;
2346  }
2347 
2348  struct MHD_Response *resp;
2349  char *result_str;
2350 
2351  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2352  cl,
2353  pl);
2354  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2355  resp = GNUNET_REST_create_response (result_str);
2356  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2357  GNUNET_free (result_str);
2358  GNUNET_free (nonce);
2361  cleanup_handle (handle);
2362 }
2363 
2364 
2372 static void
2374  const char *url,
2375  void *cls)
2376 {
2377  // TODO expiration time
2378  struct RequestHandle *handle = cls;
2379  struct GNUNET_RECLAIM_Ticket *ticket;
2380  char delimiter[] = " ";
2381  struct GNUNET_HashCode cache_key;
2382  char *authorization;
2383  char *authorization_type;
2384  char *authorization_access_token;
2385  const struct EgoEntry *aud_ego;
2386  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2387 
2388  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2391  &cache_key);
2393  ->header_param_map,
2394  &cache_key))
2395  {
2397  handle->edesc = GNUNET_strdup ("No Access Token");
2398  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2400  return;
2401  }
2402  authorization =
2404  &cache_key);
2405 
2406  // split header in "Bearer" and access_token
2407  authorization = GNUNET_strdup (authorization);
2408  authorization_type = strtok (authorization, delimiter);
2409  if ((NULL == authorization_type) ||
2410  (0 != strcmp ("Bearer", authorization_type)))
2411  {
2413  handle->edesc = GNUNET_strdup ("No Access Token");
2414  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2416  GNUNET_free (authorization);
2417  return;
2418  }
2419  authorization_access_token = strtok (NULL, delimiter);
2420  if (NULL == authorization_access_token)
2421  {
2423  handle->edesc = GNUNET_strdup ("Access token missing");
2424  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2426  GNUNET_free (authorization);
2427  return;
2428  }
2429 
2430  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2431  &ticket))
2432  {
2434  handle->edesc = GNUNET_strdup ("The access token is invalid");
2435  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2437  GNUNET_free (authorization);
2438  return;
2439 
2440  }
2441  GNUNET_assert (NULL != ticket);
2442  handle->ticket = *ticket;
2443  GNUNET_free (ticket);
2444  aud_ego = find_ego (handle, &handle->ticket.audience);
2445  if (NULL == aud_ego)
2446  {
2448  handle->edesc = GNUNET_strdup ("The access token expired");
2449  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2451  GNUNET_free (authorization);
2452  return;
2453  }
2454  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2455  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2456  handle->attr_userinfo_list =
2458  handle->presentations =
2460 
2461  /* If the consume takes too long, we use values from the cache */
2462  handle->access_token = GNUNET_strdup (authorization_access_token);
2464  &consume_timeout,
2465  handle);
2466  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2467  privkey,
2468  &handle->ticket,
2469  &consume_ticket,
2470  handle);
2471  GNUNET_free (authorization);
2472 }
2473 
2474 
2507 static void
2508 list_ego (void *cls,
2509  struct GNUNET_IDENTITY_Ego *ego,
2510  void **ctx,
2511  const char *identifier)
2512 {
2513  struct EgoEntry *ego_entry;
2514  struct GNUNET_IDENTITY_PublicKey pk;
2515 
2516  if (NULL == ego)
2517  {
2519  return;
2520  }
2521  if (ID_REST_STATE_INIT == state)
2522 
2523  {
2524  ego_entry = GNUNET_new (struct EgoEntry);
2527  ego_entry->ego = ego;
2528  ego_entry->identifier = GNUNET_strdup (identifier);
2530  ego_tail,
2531  ego_entry);
2532  return;
2533  }
2534  /* Ego renamed or added */
2535  if (identifier != NULL)
2536  {
2537  for (ego_entry = ego_head; NULL != ego_entry;
2538  ego_entry = ego_entry->next)
2539  {
2540  if (ego_entry->ego == ego)
2541  {
2542  /* Rename */
2543  GNUNET_free (ego_entry->identifier);
2544  ego_entry->identifier = GNUNET_strdup (identifier);
2545  break;
2546  }
2547  }
2548  if (NULL == ego_entry)
2549  {
2550  /* Add */
2551  ego_entry = GNUNET_new (struct EgoEntry);
2554  ego_entry->ego = ego;
2555  ego_entry->identifier = GNUNET_strdup (identifier);
2557  ego_tail,
2558  ego_entry);
2559  }
2560  }
2561  else
2562  {
2563  /* Delete */
2564  for (ego_entry = ego_head; NULL != ego_entry;
2565  ego_entry = ego_entry->next)
2566  {
2567  if (ego_entry->ego == ego)
2568  break;
2569  }
2570  if (NULL == ego_entry)
2571  return; /* Not found */
2572 
2573  GNUNET_CONTAINER_DLL_remove (ego_head,
2574  ego_tail,
2575  ego_entry);
2576  GNUNET_free (ego_entry->identifier);
2577  GNUNET_free (ego_entry->keystring);
2578  GNUNET_free (ego_entry);
2579  return;
2580  }
2581 }
2582 
2583 
2584 static void
2586  const char *url,
2587  void *cls)
2588 {
2589  json_t *oidc_config;
2590  json_t *auth_methods;
2591  json_t *sig_algs;
2592  json_t *scopes;
2593  json_t *response_types;
2594  json_t *sub_types;
2595  json_t *claim_types;
2596  char *oidc_config_str;
2597  struct MHD_Response *resp;
2598  struct RequestHandle *handle = cls;
2599 
2600  oidc_config = json_object ();
2601  // FIXME get from config?
2602  json_object_set_new (oidc_config,
2603  "issuer", json_string ("http://localhost:7776"));
2604  json_object_set_new (oidc_config,
2605  "authorization_endpoint",
2606  json_string ("https://api.reclaim/openid/authorize"));
2607  json_object_set_new (oidc_config,
2608  "token_endpoint",
2609  json_string ("http://localhost:7776/openid/token"));
2610  auth_methods = json_array ();
2611  json_array_append_new (auth_methods,
2612  json_string ("client_secret_basic"));
2613  json_array_append_new (auth_methods,
2614  json_string ("client_secret_post"));
2615  json_object_set_new (oidc_config,
2616  "token_endpoint_auth_methods_supported",
2617  auth_methods);
2618  sig_algs = json_array ();
2619  json_array_append_new (sig_algs,
2620  json_string ("HS512"));
2621  json_object_set_new (oidc_config,
2622  "id_token_signing_alg_values_supported",
2623  sig_algs);
2624  json_object_set_new (oidc_config,
2625  "userinfo_endpoint",
2626  json_string ("http://localhost:7776/openid/userinfo"));
2627  scopes = json_array ();
2628  json_array_append_new (scopes,
2629  json_string ("openid"));
2630  json_array_append_new (scopes,
2631  json_string ("profile"));
2632  json_array_append_new (scopes,
2633  json_string ("email"));
2634  json_array_append_new (scopes,
2635  json_string ("address"));
2636  json_array_append_new (scopes,
2637  json_string ("phone"));
2638  json_object_set_new (oidc_config,
2639  "scopes_supported",
2640  scopes);
2641  response_types = json_array ();
2642  json_array_append_new (response_types,
2643  json_string ("code"));
2644  json_object_set_new (oidc_config,
2645  "response_types_supported",
2646  response_types);
2647  sub_types = json_array ();
2648  json_array_append_new (sub_types,
2649  json_string ("public")); /* no pairwise support */
2650  json_object_set_new (oidc_config,
2651  "subject_types_supported",
2652  sub_types);
2653  claim_types = json_array ();
2654  json_array_append_new (claim_types,
2655  json_string ("normal"));
2656  json_array_append_new (claim_types,
2657  json_string ("aggregated"));
2658  json_object_set_new (oidc_config,
2659  "claim_types_supported",
2660  claim_types);
2661  json_object_set_new (oidc_config,
2662  "claims_parameter_supported",
2663  json_boolean (1));
2664  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2665  resp = GNUNET_REST_create_response (oidc_config_str);
2666  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2667  json_decref (oidc_config);
2668  GNUNET_free (oidc_config_str);
2669  cleanup_handle (handle);
2670 }
2671 
2672 
2680 static void
2682  const char *url,
2683  void *cls)
2684 {
2685  struct MHD_Response *resp;
2686  struct RequestHandle *handle = cls;
2687 
2688  // For now, independent of path return all options
2689  resp = GNUNET_REST_create_response (NULL);
2690  GNUNET_assert (MHD_NO !=
2691  MHD_add_response_header (resp,
2692  "Access-Control-Allow-Methods",
2693  allow_methods));
2694  GNUNET_assert (MHD_NO !=
2695  MHD_add_response_header (resp,
2696  "Access-Control-Allow-Origin",
2697  "*"));
2698  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2699  cleanup_handle (handle);
2700  return;
2701 }
2702 
2703 
2704 static enum GNUNET_GenericReturnValue
2707  void *proc_cls)
2708 {
2709  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2711  static const struct GNUNET_REST_RequestHandler handlers[] =
2712  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2713  { MHD_HTTP_METHOD_POST,
2714  GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2715  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2716  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2717  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2718  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2719  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2721  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2722  &oidc_config_cors },
2723  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2725 
2726  handle->oidc = GNUNET_new (struct OIDC_Variables);
2727  if (NULL == OIDC_cookie_jar_map)
2728  OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2729  GNUNET_NO);
2730  if (NULL == oidc_code_cache)
2731  oidc_code_cache = GNUNET_CONTAINER_multihashmap_create (10,
2732  GNUNET_NO);
2733 
2734  handle->response_code = 0;
2736  handle->proc_cls = proc_cls;
2737  handle->proc = proc;
2738  handle->rest_handle = rest_handle;
2739  handle->url = GNUNET_strdup (rest_handle->url);
2740  handle->timeout_task =
2741  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2742  GNUNET_CONTAINER_DLL_insert (requests_head,
2743  requests_tail,
2744  handle);
2745  if (handle->url[strlen (handle->url) - 1] == '/')
2746  handle->url[strlen (handle->url) - 1] = '\0';
2747  if (GNUNET_NO ==
2748  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2749  return GNUNET_NO;
2750 
2751  return GNUNET_YES;
2752 }
2753 
2754 
2761 void *
2763 {
2764  static struct Plugin plugin;
2765  struct GNUNET_REST_Plugin *api;
2766 
2767  cfg = cls;
2768  if (NULL != plugin.cfg)
2769  return NULL; /* can only initialize once! */
2770  memset (&plugin, 0, sizeof(struct Plugin));
2771  plugin.cfg = cfg;
2772  api = GNUNET_new (struct GNUNET_REST_Plugin);
2773  api->cls = &plugin;
2776  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2777  gns_handle = GNUNET_GNS_connect (cfg);
2778  idp = GNUNET_RECLAIM_connect (cfg);
2779 
2782  "%s, %s, %s, %s, %s",
2783  MHD_HTTP_METHOD_GET,
2784  MHD_HTTP_METHOD_POST,
2785  MHD_HTTP_METHOD_PUT,
2786  MHD_HTTP_METHOD_DELETE,
2787  MHD_HTTP_METHOD_OPTIONS);
2788 
2790  _ ("OpenID Connect REST API initialized\n"));
2791  return api;
2792 }
2793 
2794 
2795 static int
2796 cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2797 {
2798  GNUNET_free (value);
2799  return GNUNET_YES;
2800 }
2801 
2802 
2809 void *
2811 {
2812  struct GNUNET_REST_Plugin *api = cls;
2813  struct Plugin *plugin = api->cls;
2814  struct EgoEntry *ego_entry;
2815 
2816  plugin->cfg = NULL;
2817  while (NULL != requests_head)
2818  cleanup_handle (requests_head);
2819  if (NULL != OIDC_cookie_jar_map)
2820  {
2821  GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2822  &cleanup_hashmap,
2823  NULL);
2824  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2825  }
2826  if (NULL != oidc_code_cache)
2827  {
2828  GNUNET_CONTAINER_multihashmap_iterate (oidc_code_cache,
2829  &cleanup_hashmap,
2830  NULL);
2831  GNUNET_CONTAINER_multihashmap_destroy (oidc_code_cache);
2832  }
2833 
2835  if (NULL != gns_handle)
2836  GNUNET_GNS_disconnect (gns_handle);
2837  if (NULL != identity_handle)
2838  GNUNET_IDENTITY_disconnect (identity_handle);
2839  if (NULL != idp)
2841  while (NULL != (ego_entry = ego_head))
2842  {
2843  GNUNET_CONTAINER_DLL_remove (ego_head,
2844  ego_tail,
2845  ego_entry);
2846  GNUNET_free (ego_entry->identifier);
2847  GNUNET_free (ego_entry->keystring);
2848  GNUNET_free (ego_entry);
2849  }
2850  GNUNET_free (api);
2852  "OpenID Connect REST plugin is finished\n");
2853  return NULL;
2854 }
2855 
2856 
2857 /* 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
struct GNUNET_CONTAINER_MultiHashMap * oidc_code_cache
OIDC hashmap for cached access tokens and codes.
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:1486
Do not check code verifier even if expected.
Definition: oidc_helper.h:51
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 void consume_timeout(void *cls)
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
#define OIDC_CODE_CHALLENGE_KEY
OIDC PKCE code challenge.
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:1508
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.
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Used reclaimID OIDC client redirect URIs.
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:1439
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:181
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:1103
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:1088
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
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, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:675
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.
#define CONSUME_TIMEOUT
How long to wait for a consume in userinfo endpoint.
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1700
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:1590
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:1376
#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:796
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
enum GNUNET_GenericReturnValue 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.
#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.
static void oidc_ticket_issue_cb(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_PresentationList *presentation)
Issues ticket and redirects to relying party with the authorization code as parameter.
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:866
#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:178
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
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:41
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:1330
#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:824
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:311
#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.
char * access_token
The passed access token.
#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:86
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:371
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:489
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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.
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.
#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.
struct GNUNET_SCHEDULER_Task * consume_timeout_op
Timeout task for consume.
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.
Strict verification.
Definition: oidc_helper.h:46
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.
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:136
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.
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
enum GNUNET_GenericReturnValue 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.
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:1397
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
static void consume_ticket(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *presentation)
Collects claims and stores them in handle.
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:839
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 hashmap 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:1063
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:1541
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:344
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.