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  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
690  handle->proc (handle->proc_cls, resp, handle->response_code);
691  cleanup_handle (handle);
692  GNUNET_free (error);
693 }
694 
695 
701 static void
702 do_redirect_error (void *cls)
703 {
704  struct RequestHandle *handle = cls;
705  struct MHD_Response *resp;
706  char *redirect;
707 
708  GNUNET_asprintf (&redirect,
709  "%s?error=%s&error_description=%s%s%s",
710  handle->oidc->redirect_uri,
711  handle->emsg,
712  handle->edesc,
713  (NULL != handle->oidc->state) ? "&state=" : "",
714  (NULL != handle->oidc->state) ? handle->oidc->state : "");
715  resp = GNUNET_REST_create_response ("");
716  MHD_add_response_header (resp, "Location", redirect);
717  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
718  cleanup_handle (handle);
719  GNUNET_free (redirect);
720 }
721 
722 
728 static void
729 do_timeout (void *cls)
730 {
731  struct RequestHandle *handle = cls;
732 
733  handle->timeout_task = NULL;
734  do_error (handle);
735 }
736 
737 
745 static void
747  const char *url,
748  void *cls)
749 {
750  struct MHD_Response *resp;
751  struct RequestHandle *handle = cls;
752 
753  // For now, independent of path return all options
754  resp = GNUNET_REST_create_response (NULL);
755  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
756  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
757  cleanup_handle (handle);
758  return;
759 }
760 
761 
765 static void
767 {
768  struct GNUNET_HashCode cache_key;
769  char *cookies;
770  struct GNUNET_TIME_Absolute current_time, *relog_time;
771  char delimiter[] = "; ";
772  char *tmp_cookies;
773  char *token;
774  char *value;
775 
776  // gets identity of login try with cookie
778  strlen (OIDC_COOKIE_HEADER_KEY),
779  &cache_key);
782  &cache_key))
783  {
784  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
785  return;
786  }
787  // splits cookies and find 'Identity' cookie
788  tmp_cookies =
790  &cache_key);
791  cookies = GNUNET_strdup (tmp_cookies);
792  token = strtok (cookies, delimiter);
793  handle->oidc->user_cancelled = GNUNET_NO;
794  handle->oidc->login_identity = NULL;
795  if (NULL == token)
796  {
798  "Unable to parse cookie: %s\n",
799  cookies);
800  GNUNET_free (cookies);
801  return;
802  }
803 
804  while (NULL != token)
805  {
806  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
807  {
808  handle->oidc->user_cancelled = GNUNET_YES;
809  GNUNET_free (cookies);
810  return;
811  }
812  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
813  break;
814  token = strtok (NULL, delimiter);
815  }
816  if (NULL == token)
817  {
819  "No cookie value to process: %s\n",
820  cookies);
821  GNUNET_free (cookies);
822  return;
823  }
824  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
825  if (GNUNET_NO ==
826  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
827  {
828  GNUNET_log (
830  "Found cookie `%s', but no corresponding expiration entry present...\n",
831  token);
832  GNUNET_free (cookies);
833  return;
834  }
835  relog_time =
836  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
837  current_time = GNUNET_TIME_absolute_get ();
838  // 30 min after old login -> redirect to login
839  if (current_time.abs_value_us > relog_time->abs_value_us)
840  {
842  "Found cookie `%s', but it is expired.\n",
843  token);
844  GNUNET_free (cookies);
845  return;
846  }
847  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
848  GNUNET_assert (NULL != value);
849  handle->oidc->login_identity = GNUNET_strdup (value);
850  GNUNET_free (cookies);
851 }
852 
853 
857 static void
858 login_redirect (void *cls)
859 {
860  char *login_base_url;
861  char *new_redirect;
862  char *tmp;
863  struct MHD_Response *resp;
864  struct GNUNET_Buffer buf = { 0 };
865  struct RequestHandle *handle = cls;
866 
868  "reclaim-rest-plugin",
869  "address",
870  &login_base_url))
871  {
872  GNUNET_buffer_write_str (&buf, login_base_url);
874  "?%s=%s",
876  handle->oidc->response_type);
878  "&%s=%s",
880  handle->oidc->client_id);
882  strlen (handle->oidc->redirect_uri),
883  &tmp);
885  "&%s=%s",
887  tmp);
888  GNUNET_free (tmp);
890  strlen (handle->oidc->scope),
891  &tmp);
893  "&%s=%s",
895  tmp);
896  GNUNET_free (tmp);
897  if (NULL != handle->oidc->state)
898  {
900  strlen (handle->oidc->state),
901  &tmp);
903  "&%s=%s",
905  handle->oidc->state);
906  GNUNET_free (tmp);
907  }
908  if (NULL != handle->oidc->code_challenge)
909  {
911  "&%s=%s",
913  handle->oidc->code_challenge);
914  }
915  if (NULL != handle->oidc->nonce)
916  {
918  "&%s=%s",
920  handle->oidc->nonce);
921  }
922  if (NULL != handle->oidc->claims)
923  {
925  strlen (handle->oidc->claims),
926  &tmp);
928  "&%s=%s",
930  tmp);
931  GNUNET_free (tmp);
932  }
933  new_redirect = GNUNET_buffer_reap_str (&buf);
934  resp = GNUNET_REST_create_response ("");
935  MHD_add_response_header (resp, "Location", new_redirect);
936  GNUNET_free (login_base_url);
937  }
938  else
939  {
941  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
942  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
944  return;
945  }
946  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
947  GNUNET_free (new_redirect);
948  cleanup_handle (handle);
949 }
950 
951 
955 static void
957 {
958  struct RequestHandle *handle = cls;
959 
961  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
963 }
964 
965 
970 static void
972  const struct GNUNET_RECLAIM_Ticket *ticket,
973  const struct GNUNET_RECLAIM_PresentationList *pres)
974 {
975  struct RequestHandle *handle = cls;
976  struct MHD_Response *resp;
977  char *ticket_str;
978  char *redirect_uri;
979  char *code_string;
980 
981  handle->idp_op = NULL;
982  if (NULL == ticket)
983  {
985  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
987  return;
988  }
989  handle->ticket = *ticket;
990  ticket_str =
992  sizeof(struct GNUNET_RECLAIM_Ticket));
993  code_string = OIDC_build_authz_code (&handle->priv_key,
994  &handle->ticket,
995  handle->attr_idtoken_list,
996  pres,
997  handle->oidc->nonce,
998  handle->oidc->code_challenge);
999  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1000  (NULL != handle->tld))
1001  {
1002  GNUNET_asprintf (&redirect_uri,
1003  "%s.%s/%s%s%s=%s&state=%s",
1004  handle->redirect_prefix,
1005  handle->tld,
1006  handle->redirect_suffix,
1007  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1008  "&"),
1009  handle->oidc->response_type,
1010  code_string,
1011  handle->oidc->state);
1012  }
1013  else
1014  {
1015  GNUNET_asprintf (&redirect_uri,
1016  "%s%s%s=%s&state=%s",
1017  handle->oidc->redirect_uri,
1018  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1019  "&"),
1020  handle->oidc->response_type,
1021  code_string,
1022  handle->oidc->state);
1023  }
1024  resp = GNUNET_REST_create_response ("");
1025  MHD_add_response_header (resp, "Location", redirect_uri);
1026  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1027  cleanup_handle (handle);
1028  GNUNET_free (redirect_uri);
1029  GNUNET_free (ticket_str);
1030  GNUNET_free (code_string);
1031 }
1032 
1033 
1034 static struct GNUNET_RECLAIM_AttributeList*
1036  struct GNUNET_RECLAIM_AttributeList *list_b)
1037 {
1038  struct GNUNET_RECLAIM_AttributeList *merged_list;
1039  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1040  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1041  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1042 
1043  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1044  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1045  {
1048  &le_a->attribute->
1049  credential,
1050  le_a->attribute->type,
1051  le_a->attribute->data,
1052  le_a->attribute->data_size);
1053  le_m->attribute->id = le_a->attribute->id;
1054  le_m->attribute->flag = le_a->attribute->flag;
1055  le_m->attribute->credential = le_a->attribute->credential;
1056  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1057  merged_list->list_tail,
1058  le_m);
1059  }
1060  le_m = NULL;
1061  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1062  {
1063  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1064  {
1066  &le_b->attribute->id))
1067  break;
1068  }
1069  if (NULL != le_m)
1070  continue;
1073  &le_b->attribute->
1074  credential,
1075  le_b->attribute->type,
1076  le_b->attribute->data,
1077  le_b->attribute->data_size);
1078  le_m->attribute->id = le_b->attribute->id;
1079  le_m->attribute->flag = le_b->attribute->flag;
1080  le_m->attribute->credential = le_b->attribute->credential;
1081  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1082  merged_list->list_tail,
1083  le_m);
1084  }
1085  return merged_list;
1086 }
1087 
1088 
1089 static void
1091 {
1092  struct RequestHandle *handle = cls;
1093  struct GNUNET_RECLAIM_AttributeList *merged_list;
1094  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1095 
1096  handle->cred_it = NULL;
1097  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1098  handle->attr_userinfo_list);
1099  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1101  "List Attibute in ticket to issue: %s\n",
1102  le_m->attribute->name);
1103  handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1104  &handle->priv_key,
1105  &handle->oidc->client_pkey,
1106  merged_list,
1108  handle);
1110 }
1111 
1112 
1116 static void
1118  const struct GNUNET_IDENTITY_PublicKey *identity,
1119  const struct GNUNET_RECLAIM_Credential *cred)
1120 {
1121  struct RequestHandle *handle = cls;
1124 
1125  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1126  {
1128  &cred->id))
1129  continue;
1132  return;
1133  }
1134 
1135  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1136  {
1138  &cred->id))
1139  continue;
1143  cred->type,
1144  cred->data,
1145  cred->data_size);
1147  handle->credentials->list_tail,
1148  ale);
1149  }
1151 }
1152 
1153 
1154 static void
1156 {
1157  struct RequestHandle *handle = cls;
1158 
1159  handle->attr_it = NULL;
1160  handle->ticket_it = NULL;
1161  if (NULL == handle->attr_idtoken_list->list_head)
1162  {
1164  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1166  return;
1167  }
1169  handle->cred_it =
1171  &handle->priv_key,
1173  handle,
1175  handle,
1177  handle);
1178 
1179 }
1180 
1181 
1182 static int
1184  const char *attr_name,
1185  const char *claims_parameter)
1186 {
1187  int ret = GNUNET_NO;
1188  json_t *root;
1189  json_error_t error;
1190  json_t *claims_j;
1191  const char *key;
1192  json_t *value;
1193 
1196  attr_name))
1197  return GNUNET_YES;
1198 
1200  if (NULL != handle->oidc->claims)
1201  {
1202  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1203  claims_j = json_object_get (root, claims_parameter);
1204  /* obj is a JSON object */
1205  if (NULL != claims_j)
1206  {
1207  json_object_foreach (claims_j, key, value) {
1208  if (0 != strcmp (attr_name, key))
1209  continue;
1210  ret = GNUNET_YES;
1211  break;
1212  }
1213  }
1214  json_decref (root);
1215  }
1216  return ret;
1217 }
1218 
1219 
1220 static int
1222  const char *attr_name)
1223 {
1224  return attr_in_claims_request (handle, attr_name, "id_token");
1225 }
1226 
1227 
1228 static int
1230  const char *attr_name)
1231 {
1232  return attr_in_claims_request (handle, attr_name, "userinfo");
1233 }
1234 
1235 
1239 static void
1241  const struct GNUNET_IDENTITY_PublicKey *identity,
1242  const struct GNUNET_RECLAIM_Attribute *attr)
1243 {
1244  struct RequestHandle *handle = cls;
1246  if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1247  {
1250  &attr->credential,
1251  attr->type,
1252  attr->data,
1253  attr->data_size);
1254  le->attribute->id = attr->id;
1255  le->attribute->flag = attr->flag;
1256  le->attribute->credential = attr->credential;
1258  handle->attr_idtoken_list->list_tail,
1259  le);
1260  }
1261  if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1262  {
1265  &attr->credential,
1266  attr->type,
1267  attr->data,
1268  attr->data_size);
1269  le->attribute->id = attr->id;
1270  le->attribute->flag = attr->flag;
1271  le->attribute->credential = attr->credential;
1273  handle->attr_userinfo_list->list_tail,
1274  le);
1275  }
1276 
1278 }
1279 
1280 
1284 static void
1285 code_redirect (void *cls)
1286 {
1287  struct RequestHandle *handle = cls;
1288  struct GNUNET_TIME_Absolute current_time;
1289  struct GNUNET_TIME_Absolute *relog_time;
1290  struct GNUNET_IDENTITY_PublicKey pubkey;
1291  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1292  struct GNUNET_HashCode cache_key;
1293  char *identity_cookie;
1294 
1295  GNUNET_asprintf (&identity_cookie,
1296  "Identity=%s",
1297  handle->oidc->login_identity);
1298  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1299  GNUNET_free (identity_cookie);
1300  // No login time for identity -> redirect to login
1301  if (GNUNET_YES ==
1302  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1303  {
1304  relog_time =
1305  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1306  current_time = GNUNET_TIME_absolute_get ();
1307  // 30 min after old login -> redirect to login
1308  if (current_time.abs_value_us <= relog_time->abs_value_us)
1309  {
1310  if (GNUNET_OK !=
1312  ->login_identity,
1313  &pubkey))
1314  {
1316  handle->edesc =
1317  GNUNET_strdup ("The cookie of a login identity is not valid");
1319  return;
1320  }
1321  // iterate over egos and compare their public key
1322  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1323  handle->ego_entry = handle->ego_entry->next)
1324  {
1325  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1326  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1327  {
1328  handle->priv_key =
1330  handle->attr_idtoken_list =
1332  handle->attr_userinfo_list =
1334  handle->attr_it =
1336  &handle->priv_key,
1338  handle,
1340  handle,
1342  handle);
1343  return;
1344  }
1345  }
1347  return;
1348  }
1349  }
1350 }
1351 
1352 
1353 static void
1354 build_redirect (void *cls)
1355 {
1356  struct RequestHandle *handle = cls;
1357  struct MHD_Response *resp;
1358  char *redirect_uri;
1359 
1360  if (GNUNET_YES == handle->oidc->user_cancelled)
1361  {
1362  if ((NULL != handle->redirect_prefix) &&
1363  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1364  {
1365  GNUNET_asprintf (&redirect_uri,
1366  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1367  handle->redirect_prefix,
1368  handle->tld,
1369  handle->redirect_suffix,
1370  "access_denied",
1371  "User denied access",
1372  handle->oidc->state);
1373  }
1374  else
1375  {
1376  GNUNET_asprintf (&redirect_uri,
1377  "%s?error=%s&error_description=%s&state=%s",
1378  handle->oidc->redirect_uri,
1379  "access_denied",
1380  "User denied access",
1381  handle->oidc->state);
1382  }
1383  resp = GNUNET_REST_create_response ("");
1384  MHD_add_response_header (resp, "Location", redirect_uri);
1385  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1386  cleanup_handle (handle);
1387  GNUNET_free (redirect_uri);
1388  return;
1389  }
1391 }
1392 
1393 
1394 static void
1396  uint32_t rd_count,
1397  const struct GNUNET_GNSRECORD_Data *rd)
1398 {
1399  struct RequestHandle *handle = cls;
1400  char *tmp;
1401  char *tmp_key_str;
1402  char *pos;
1403  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1404 
1405  handle->gns_op = NULL;
1406  if (0 == rd_count)
1407  {
1409  handle->edesc =
1410  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1412  return;
1413  }
1414  for (int i = 0; i < rd_count; i++)
1415  {
1416  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1417  continue;
1418  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1419  continue;
1420  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1421  if (NULL == strstr (tmp, handle->oidc->client_id))
1422  {
1424  "Redirect uri %s does not contain client_id %s\n",
1425  tmp,
1426  handle->oidc->client_id);
1427  }
1428  else
1429  {
1430  pos = strrchr (tmp, (unsigned char) '.');
1431  if (NULL == pos)
1432  {
1434  "Redirect uri %s contains client_id but is malformed\n",
1435  tmp);
1436  GNUNET_free (tmp);
1437  continue;
1438  }
1439  *pos = '\0';
1440  handle->redirect_prefix = GNUNET_strdup (tmp);
1441  tmp_key_str = pos + 1;
1442  pos = strchr (tmp_key_str, (unsigned char) '/');
1443  if (NULL == pos)
1444  {
1446  "Redirect uri %s contains client_id but is malformed\n",
1447  tmp);
1448  GNUNET_free (tmp);
1449  continue;
1450  }
1451  *pos = '\0';
1452  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1453 
1454  GNUNET_STRINGS_string_to_data (tmp_key_str,
1455  strlen (tmp_key_str),
1456  &redirect_zone,
1457  sizeof(redirect_zone));
1458  }
1460  GNUNET_free (tmp);
1461  return;
1462  }
1464  handle->edesc =
1465  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1467 }
1468 
1469 
1473 static void
1474 client_redirect (void *cls)
1475 {
1476  struct RequestHandle *handle = cls;
1477 
1478  /* Lookup client redirect uri to verify request */
1479  handle->gns_op =
1480  GNUNET_GNS_lookup (gns_handle,
1482  &handle->oidc->client_pkey,
1486  handle);
1487 }
1488 
1489 
1490 static char *
1491 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1492 {
1493  struct GNUNET_HashCode hc;
1494  char *value;
1495  char *res;
1496 
1497  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1499  ->url_param_map,
1500  &hc))
1501  return NULL;
1502  value =
1504  if (NULL == value)
1505  return NULL;
1506  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1507  return res;
1508 }
1509 
1510 
1517 static void
1519 {
1520  struct RequestHandle *handle = cls;
1521  struct GNUNET_HashCode cache_key;
1522 
1523  char *expected_scope;
1524  char delimiter[] = " ";
1525  int number_of_ignored_parameter, iterator;
1526 
1527 
1528  // REQUIRED value: redirect_uri
1529  handle->oidc->redirect_uri =
1531  if (NULL == handle->oidc->redirect_uri)
1532  {
1534  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1536  return;
1537  }
1538 
1539  // REQUIRED value: response_type
1540  handle->oidc->response_type =
1542  if (NULL == handle->oidc->response_type)
1543  {
1545  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1547  return;
1548  }
1549 
1550  // REQUIRED value: scope
1551  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1552  if (NULL == handle->oidc->scope)
1553  {
1555  handle->edesc = GNUNET_strdup ("missing parameter scope");
1557  return;
1558  }
1559 
1560  // OPTIONAL value: nonce
1561  handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1562 
1563  // OPTIONAL value: claims
1564  handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1565 
1566  // TODO check other values if needed
1567  number_of_ignored_parameter =
1568  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1569  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1570  {
1572  strlen (OIDC_ignored_parameter_array[iterator]),
1573  &cache_key);
1574  if (GNUNET_YES ==
1576  ->url_param_map,
1577  &cache_key))
1578  {
1580  GNUNET_asprintf (&handle->edesc,
1581  "Server will not handle parameter: %s",
1582  OIDC_ignored_parameter_array[iterator]);
1584  return;
1585  }
1586  }
1587 
1588  // We only support authorization code flows.
1589  if (0 != strcmp (handle->oidc->response_type,
1591  {
1593  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1594  "obtaining this authorization code.");
1596  return;
1597  }
1598 
1599  // Checks if scope contains 'openid'
1600  expected_scope = GNUNET_strdup (handle->oidc->scope);
1601  char *test;
1602  test = strtok (expected_scope, delimiter);
1603  while (NULL != test)
1604  {
1605  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1606  break;
1607  test = strtok (NULL, delimiter);
1608  }
1609  if (NULL == test)
1610  {
1612  handle->edesc =
1613  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1615  GNUNET_free (expected_scope);
1616  return;
1617  }
1618 
1619  GNUNET_free (expected_scope);
1620  if ((NULL == handle->oidc->login_identity) &&
1621  (GNUNET_NO == handle->oidc->user_cancelled))
1623  else
1625 }
1626 
1627 
1631 static void
1632 tld_iter (void *cls, const char *section, const char *option, const char *value)
1633 {
1634  struct RequestHandle *handle = cls;
1635  struct GNUNET_IDENTITY_PublicKey pkey;
1636 
1637  if (GNUNET_OK !=
1639  {
1640  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1641  return;
1642  }
1643  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1644  handle->tld = GNUNET_strdup (option + 1);
1645 }
1646 
1647 
1655 static void
1657  const char *url,
1658  void *cls)
1659 {
1660  struct RequestHandle *handle = cls;
1661  struct EgoEntry *tmp_ego;
1662  const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1663  struct GNUNET_IDENTITY_PublicKey pkey;
1664 
1666 
1667  // RECOMMENDED value: state - REQUIRED for answers
1668  handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1669 
1670  // REQUIRED value: client_id
1672  if (NULL == handle->oidc->client_id)
1673  {
1675  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1676  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1678  return;
1679  }
1680 
1681  // OPTIONAL value: code_challenge
1682  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1684  if (NULL == handle->oidc->code_challenge)
1685  {
1687  "OAuth authorization request does not contain PKCE parameters!\n");
1688  }
1689 
1690  if (GNUNET_OK !=
1692  &handle->oidc->client_pkey))
1693  {
1695  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1696  "authorization code using this method.");
1697  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1699  return;
1700  }
1701 
1702  // If we know this identity, translated the corresponding TLD
1703  // TODO: We might want to have a reverse lookup functionality for TLDs?
1704  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1705  {
1706  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1707  GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1708  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1709  {
1710  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1711  handle->ego_entry = ego_tail;
1712  }
1713  }
1714  if (NULL == handle->tld)
1716  if (NULL == handle->tld)
1717  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1719 }
1720 
1721 
1729 static void
1731  const char *url,
1732  void *cls)
1733 {
1734  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1735  struct RequestHandle *handle = cls;
1736  struct GNUNET_HashCode cache_key;
1737  struct GNUNET_TIME_Absolute *current_time;
1738  struct GNUNET_TIME_Absolute *last_time;
1739  char *cookie;
1740  char *header_val;
1741  json_t *root;
1742  json_error_t error;
1743  json_t *identity;
1744  char term_data[handle->rest_handle->data_size + 1];
1745 
1746  term_data[handle->rest_handle->data_size] = '\0';
1747  GNUNET_memcpy (term_data,
1748  handle->rest_handle->data,
1749  handle->rest_handle->data_size);
1750  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1751  identity = json_object_get (root, "identity");
1752  if (! json_is_string (identity))
1753  {
1755  "Error parsing json string from %s\n",
1756  term_data);
1757  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1758  json_decref (root);
1759  cleanup_handle (handle);
1760  return;
1761  }
1762  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1763  GNUNET_asprintf (&header_val,
1764  "%s;Max-Age=%d",
1765  cookie,
1767  MHD_add_response_header (resp, "Set-Cookie", header_val);
1768  MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
1769  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1770 
1771  if (0 != strcmp (json_string_value (identity), "Denied"))
1772  {
1773  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1774  *current_time = GNUNET_TIME_relative_to_absolute (
1777  last_time =
1778  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1779  GNUNET_free (last_time);
1780  GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1781  &cache_key,
1782  current_time,
1784  }
1785  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1786  GNUNET_free (cookie);
1787  GNUNET_free (header_val);
1788  json_decref (root);
1789  cleanup_handle (handle);
1790 }
1791 
1792 
1793 static int
1795  char **client_id,
1796  char **client_secret)
1797 {
1798  struct GNUNET_HashCode cache_key;
1799  char *authorization;
1800  char *credentials;
1801  char *basic_authorization;
1802  char *client_id_tmp;
1803  char *pass;
1804 
1807  &cache_key);
1809  ->header_param_map,
1810  &cache_key))
1811  return GNUNET_SYSERR;
1812  authorization =
1814  &cache_key);
1815 
1816  // split header in "Basic" and [content]
1817  credentials = strtok (authorization, " ");
1818  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1819  return GNUNET_SYSERR;
1820  credentials = strtok (NULL, " ");
1821  if (NULL == credentials)
1822  return GNUNET_SYSERR;
1823  GNUNET_STRINGS_base64_decode (credentials,
1824  strlen (credentials),
1825  (void **) &basic_authorization);
1826 
1827  if (NULL == basic_authorization)
1828  return GNUNET_SYSERR;
1829  client_id_tmp = strtok (basic_authorization, ":");
1830  if (NULL == client_id_tmp)
1831  {
1832  GNUNET_free (basic_authorization);
1833  return GNUNET_SYSERR;
1834  }
1835  pass = strtok (NULL, ":");
1836  if (NULL == pass)
1837  {
1838  GNUNET_free (basic_authorization);
1839  return GNUNET_SYSERR;
1840  }
1841  *client_id = strdup (client_id_tmp);
1842  *client_secret = strdup (pass);
1843  GNUNET_free (basic_authorization);
1844  return GNUNET_OK;
1845 }
1846 
1847 
1848 static int
1850  char **client_id,
1851  char **client_secret)
1852 {
1853  struct GNUNET_HashCode cache_key;
1854  char *client_id_tmp;
1855  char *pass;
1856 
1857  GNUNET_CRYPTO_hash ("client_id",
1858  strlen ("client_id"),
1859  &cache_key);
1861  ->url_param_map,
1862  &cache_key))
1863  return GNUNET_SYSERR;
1864  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1865  handle->rest_handle->url_param_map,
1866  &cache_key);
1867  if (NULL == client_id_tmp)
1868  return GNUNET_SYSERR;
1869  *client_id = strdup (client_id_tmp);
1870  GNUNET_CRYPTO_hash ("client_secret",
1871  strlen ("client_secret"),
1872  &cache_key);
1874  ->url_param_map,
1875  &cache_key))
1876  {
1877  GNUNET_free (*client_id);
1878  *client_id = NULL;
1879  return GNUNET_SYSERR;
1880  }
1882  &cache_key);
1883  if (NULL == pass) {
1884  GNUNET_free (*client_id);
1885  *client_id = NULL;
1886  return GNUNET_SYSERR;
1887  }
1888  *client_secret = strdup (pass);
1889  return GNUNET_OK;
1890 }
1891 
1892 
1893 static int
1895  struct GNUNET_IDENTITY_PublicKey *cid)
1896 {
1897  char *expected_pass;
1898  char *received_cid;
1899  char *received_cpw;
1900  char *pkce_cv;
1901 
1902  if (GNUNET_OK == parse_credentials_basic_auth (handle,
1903  &received_cid,
1904  &received_cpw))
1905  {
1907  "Received client credentials in HTTP AuthZ header\n");
1908  }
1909  else if (GNUNET_OK == parse_credentials_post_body (handle,
1910  &received_cid,
1911  &received_cpw))
1912  {
1914  "Received client credentials in POST body\n");
1915  }
1916  else
1917  {
1919  pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1920  if (NULL == pkce_cv)
1921  {
1923  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1924  return GNUNET_SYSERR;
1925  }
1926  handle->public_client = GNUNET_YES;
1927  GNUNET_free (pkce_cv);
1928  received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1929  GNUNET_STRINGS_string_to_data (received_cid,
1930  strlen (received_cid),
1931  cid,
1932  sizeof(struct GNUNET_IDENTITY_PublicKey));
1933  GNUNET_free (received_cid);
1934  return GNUNET_OK;
1935 
1936  }
1937 
1938  // check client password
1940  "reclaim-rest-plugin",
1941  "OIDC_CLIENT_SECRET",
1942  &expected_pass))
1943  {
1944  if (0 != strcmp (expected_pass, received_cpw))
1945  {
1946  GNUNET_free (expected_pass);
1948  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1949  GNUNET_free (received_cpw);
1950  GNUNET_free (received_cid);
1951  return GNUNET_SYSERR;
1952  }
1953  GNUNET_free (expected_pass);
1954  }
1955  else
1956  {
1957  GNUNET_free (received_cpw);
1958  GNUNET_free (received_cid);
1960  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1961  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1962  return GNUNET_SYSERR;
1963  }
1964  // check client_id
1965  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1966  handle->ego_entry = handle->ego_entry->next)
1967  {
1968  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1969  break;
1970  }
1971  if (NULL == handle->ego_entry)
1972  {
1973  GNUNET_free (received_cpw);
1974  GNUNET_free (received_cid);
1976  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1977  return GNUNET_SYSERR;
1978  }
1979  GNUNET_STRINGS_string_to_data (received_cid,
1980  strlen (received_cid),
1981  cid,
1982  sizeof(struct GNUNET_IDENTITY_PublicKey));
1983 
1984  GNUNET_free (received_cpw);
1985  GNUNET_free (received_cid);
1986  return GNUNET_OK;
1987 }
1988 
1989 
1990 const struct EgoEntry *
1992  struct GNUNET_IDENTITY_PublicKey *test_key)
1993 {
1994  struct EgoEntry *ego_entry;
1995  struct GNUNET_IDENTITY_PublicKey pub_key;
1996 
1997  for (ego_entry = ego_head; NULL != ego_entry;
1998  ego_entry = ego_entry->next)
1999  {
2000  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2001  if (0 == GNUNET_memcmp (&pub_key, test_key))
2002  return ego_entry;
2003  }
2004  return NULL;
2005 }
2006 
2007 
2015 static void
2017  const char *url,
2018  void *cls)
2019 {
2020  struct RequestHandle *handle = cls;
2021  const struct EgoEntry *ego_entry;
2022  struct GNUNET_TIME_Relative expiration_time;
2023  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2024  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2025  struct GNUNET_RECLAIM_Ticket ticket;
2026  struct GNUNET_IDENTITY_PublicKey cid;
2027  struct GNUNET_HashCode cache_key;
2028  struct MHD_Response *resp;
2029  char *grant_type;
2030  char *code;
2031  char *json_response;
2032  char *id_token;
2033  char *access_token;
2034  char *jwt_secret;
2035  char *nonce = NULL;
2036  char *code_verifier;
2037 
2038  /*
2039  * Check Authorization
2040  */
2041  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2042  {
2044  "OIDC authorization for token endpoint failed\n");
2046  return;
2047  }
2048 
2049  /*
2050  * Check parameter
2051  */
2052 
2053  // TODO Do not allow multiple equal parameter names
2054  // REQUIRED grant_type
2056  strlen (OIDC_GRANT_TYPE_KEY),
2057  &cache_key);
2058  grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2059  if (NULL == grant_type)
2060  {
2062  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2063  handle->response_code = MHD_HTTP_BAD_REQUEST;
2065  return;
2066  }
2067 
2068  // Check parameter grant_type == "authorization_code"
2069  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2070  {
2072  handle->response_code = MHD_HTTP_BAD_REQUEST;
2073  GNUNET_free (grant_type);
2075  return;
2076  }
2077  GNUNET_free (grant_type);
2078  // REQUIRED code
2079  code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2080  if (NULL == code)
2081  {
2083  handle->edesc = GNUNET_strdup ("missing parameter code");
2084  handle->response_code = MHD_HTTP_BAD_REQUEST;
2086  return;
2087  }
2088  ego_entry = find_ego (handle, &cid);
2089  if (NULL == ego_entry)
2090  {
2092  handle->edesc = GNUNET_strdup ("Unknown client");
2093  handle->response_code = MHD_HTTP_BAD_REQUEST;
2094  GNUNET_free (code);
2096  return;
2097  }
2098 
2099  // REQUIRED code verifier
2100  code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2101  if (NULL == code_verifier)
2102  {
2104  "OAuth authorization request does not contain PKCE parameters!\n");
2105 
2106  }
2107 
2108  // decode code
2109  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2110  &cl, &pl, &nonce,
2112  {
2114  handle->edesc = GNUNET_strdup ("invalid code");
2115  handle->response_code = MHD_HTTP_BAD_REQUEST;
2116  GNUNET_free (code);
2117  if (NULL != code_verifier)
2118  GNUNET_free (code_verifier);
2120  return;
2121  }
2122  if (NULL != code_verifier)
2123  GNUNET_free (code_verifier);
2124 
2125  // create jwt
2127  "reclaim-rest-plugin",
2128  "expiration_time",
2129  &expiration_time))
2130  {
2132  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2133  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2134  GNUNET_free (code);
2135  if (NULL != nonce)
2136  GNUNET_free (nonce);
2138  return;
2139  }
2140 
2141 
2142  // TODO OPTIONAL acr,amr,azp
2144  "reclaim-rest-plugin",
2145  "jwt_secret",
2146  &jwt_secret))
2147  {
2149  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2150  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2151  GNUNET_free (code);
2152  if (NULL != nonce)
2153  GNUNET_free (nonce);
2155  return;
2156  }
2157  id_token = OIDC_generate_id_token (&ticket.audience,
2158  &ticket.identity,
2159  cl,
2160  pl,
2161  &expiration_time,
2162  (NULL != nonce) ? nonce : NULL,
2163  jwt_secret);
2164  GNUNET_free (jwt_secret);
2165  if (NULL != nonce)
2166  GNUNET_free (nonce);
2167  access_token = OIDC_access_token_new (&ticket);
2168  /* Store mapping from access token to code so we can later
2169  * fall back on the provided attributes in userinfo
2170  */
2171  GNUNET_CRYPTO_hash (access_token,
2172  strlen (access_token),
2173  &cache_key);
2174  char *tmp_at = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2175  &cache_key);
2176  GNUNET_CONTAINER_multihashmap_put (oidc_code_cache,
2177  &cache_key,
2178  code,
2180  /* If there was a previus code in there, free the old value */
2181  if (NULL != tmp_at)
2182  {
2184  "OIDC access token already issued. Cleanup.\n");
2185  GNUNET_free (tmp_at);
2186  }
2187 
2188  OIDC_build_token_response (access_token,
2189  id_token,
2190  &expiration_time,
2191  &json_response);
2192 
2193  resp = GNUNET_REST_create_response (json_response);
2194  MHD_add_response_header (resp, "Cache-Control", "no-store");
2195  MHD_add_response_header (resp, "Pragma", "no-cache");
2196  MHD_add_response_header (resp, "Content-Type", "application/json");
2197  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2200  GNUNET_free (access_token);
2201  GNUNET_free (json_response);
2202  GNUNET_free (id_token);
2203  cleanup_handle (handle);
2204 }
2205 
2206 
2210 static void
2211 consume_ticket (void *cls,
2212  const struct GNUNET_IDENTITY_PublicKey *identity,
2213  const struct GNUNET_RECLAIM_Attribute *attr,
2214  const struct GNUNET_RECLAIM_Presentation *pres)
2215 {
2216  struct RequestHandle *handle = cls;
2219  struct MHD_Response *resp;
2220  char *result_str;
2221 
2222  if (NULL != handle->consume_timeout_op)
2224  handle->consume_timeout_op = NULL;
2225  handle->idp_op = NULL;
2226 
2227  if (NULL == identity)
2228  {
2229  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2230  handle->attr_userinfo_list,
2231  handle->presentations);
2232  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2233  resp = GNUNET_REST_create_response (result_str);
2234  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2235  GNUNET_free (result_str);
2236  cleanup_handle (handle);
2237  return;
2238  }
2241  &attr->credential,
2242  attr->type,
2243  attr->data,
2244  attr->data_size);
2245  ale->attribute->id = attr->id;
2246  ale->attribute->flag = attr->flag;
2247  ale->attribute->credential = attr->credential;
2249  handle->attr_userinfo_list->list_tail,
2250  ale);
2251  if (NULL == pres)
2252  return;
2253  for (atle = handle->presentations->list_head;
2254  NULL != atle; atle = atle->next)
2255  {
2257  &atle->presentation->credential_id,
2258  &pres->credential_id))
2259  continue;
2260  break;
2261  }
2262  if (NULL == atle)
2263  {
2267  pres->data,
2268  pres->data_size);
2269  atle->presentation->credential_id = pres->credential_id;
2271  handle->presentations->list_tail,
2272  atle);
2273  }
2274 }
2275 
2276 
2277 static void
2279 {
2280  struct RequestHandle *handle = cls;
2281  struct GNUNET_HashCode cache_key;
2282  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2283  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2284  struct GNUNET_RECLAIM_Ticket ticket;
2285  char *nonce;
2286  char *cached_code;
2287 
2288  handle->consume_timeout_op = NULL;
2289  if (NULL != handle->idp_op)
2290  GNUNET_RECLAIM_cancel (handle->idp_op);
2291  handle->idp_op = NULL;
2292 
2294  "Ticket consumptioned timed out. Using cache...\n");
2296  strlen (handle->access_token),
2297  &cache_key);
2298  cached_code = GNUNET_CONTAINER_multihashmap_get (oidc_code_cache,
2299  &cache_key);
2300  if (NULL == cached_code)
2301  {
2303  handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2304  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2306  return;
2307  }
2308 
2309  // decode code
2311  cached_code, NULL, &ticket,
2312  &cl, &pl, &nonce,
2314  {
2316  handle->edesc = GNUNET_strdup ("invalid code");
2317  handle->response_code = MHD_HTTP_BAD_REQUEST;
2318  GNUNET_free (cached_code);
2319  if (NULL != nonce)
2320  GNUNET_free (nonce);
2322  return;
2323  }
2324 
2325  struct MHD_Response *resp;
2326  char *result_str;
2327 
2328  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2329  cl,
2330  pl);
2331  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2332  resp = GNUNET_REST_create_response (result_str);
2333  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2334  GNUNET_free (result_str);
2335  GNUNET_free (nonce);
2338  cleanup_handle (handle);
2339 }
2340 
2341 
2349 static void
2351  const char *url,
2352  void *cls)
2353 {
2354  // TODO expiration time
2355  struct RequestHandle *handle = cls;
2356  struct GNUNET_RECLAIM_Ticket *ticket;
2357  char delimiter[] = " ";
2358  struct GNUNET_HashCode cache_key;
2359  char *authorization;
2360  char *authorization_type;
2361  char *authorization_access_token;
2362  const struct EgoEntry *aud_ego;
2363  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2364 
2365  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2368  &cache_key);
2370  ->header_param_map,
2371  &cache_key))
2372  {
2374  handle->edesc = GNUNET_strdup ("No Access Token");
2375  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2377  return;
2378  }
2379  authorization =
2381  &cache_key);
2382 
2383  // split header in "Bearer" and access_token
2384  authorization = GNUNET_strdup (authorization);
2385  authorization_type = strtok (authorization, delimiter);
2386  if ((NULL == authorization_type) ||
2387  (0 != strcmp ("Bearer", authorization_type)))
2388  {
2390  handle->edesc = GNUNET_strdup ("No Access Token");
2391  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2393  GNUNET_free (authorization);
2394  return;
2395  }
2396  authorization_access_token = strtok (NULL, delimiter);
2397  if (NULL == authorization_access_token)
2398  {
2400  handle->edesc = GNUNET_strdup ("Access token missing");
2401  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2403  GNUNET_free (authorization);
2404  return;
2405  }
2406 
2407  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2408  &ticket))
2409  {
2411  handle->edesc = GNUNET_strdup ("The access token is invalid");
2412  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2414  GNUNET_free (authorization);
2415  return;
2416 
2417  }
2418  GNUNET_assert (NULL != ticket);
2419  handle->ticket = *ticket;
2420  GNUNET_free (ticket);
2421  aud_ego = find_ego (handle, &handle->ticket.audience);
2422  if (NULL == aud_ego)
2423  {
2425  handle->edesc = GNUNET_strdup ("The access token expired");
2426  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2428  GNUNET_free (authorization);
2429  return;
2430  }
2431  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2432  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2433  handle->attr_userinfo_list =
2435  handle->presentations =
2437 
2438  /* If the consume takes too long, we use values from the cache */
2439  handle->access_token = GNUNET_strdup (authorization_access_token);
2441  &consume_timeout,
2442  handle);
2443  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2444  privkey,
2445  &handle->ticket,
2446  &consume_ticket,
2447  handle);
2448  GNUNET_free (authorization);
2449 }
2450 
2451 
2485 static void
2486 list_ego (void *cls,
2487  struct GNUNET_IDENTITY_Ego *ego,
2488  void **ctx,
2489  const char *identifier)
2490 {
2491  struct EgoEntry *ego_entry;
2492  struct GNUNET_IDENTITY_PublicKey pk;
2493 
2494  if (NULL == ego)
2495  {
2497  return;
2498  }
2499  if (ID_REST_STATE_INIT == state)
2500 
2501  {
2502  ego_entry = GNUNET_new (struct EgoEntry);
2505  ego_entry->ego = ego;
2506  ego_entry->identifier = GNUNET_strdup (identifier);
2508  ego_tail,
2509  ego_entry);
2510  return;
2511  }
2512  /* Ego renamed or added */
2513  if (identifier != NULL)
2514  {
2515  for (ego_entry = ego_head; NULL != ego_entry;
2516  ego_entry = ego_entry->next)
2517  {
2518  if (ego_entry->ego == ego)
2519  {
2520  /* Rename */
2521  GNUNET_free (ego_entry->identifier);
2522  ego_entry->identifier = GNUNET_strdup (identifier);
2523  break;
2524  }
2525  }
2526  if (NULL == ego_entry)
2527  {
2528  /* Add */
2529  ego_entry = GNUNET_new (struct EgoEntry);
2532  ego_entry->ego = ego;
2533  ego_entry->identifier = GNUNET_strdup (identifier);
2535  ego_tail,
2536  ego_entry);
2537  }
2538  }
2539  else
2540  {
2541  /* Delete */
2542  for (ego_entry = ego_head; NULL != ego_entry;
2543  ego_entry = ego_entry->next)
2544  {
2545  if (ego_entry->ego == ego)
2546  break;
2547  }
2548  if (NULL == ego_entry)
2549  return; /* Not found */
2550 
2551  GNUNET_CONTAINER_DLL_remove (ego_head,
2552  ego_tail,
2553  ego_entry);
2554  GNUNET_free (ego_entry->identifier);
2555  GNUNET_free (ego_entry->keystring);
2556  GNUNET_free (ego_entry);
2557  return;
2558  }
2559 }
2560 
2561 
2562 static void
2564  const char *url,
2565  void *cls)
2566 {
2567  json_t *oidc_config;
2568  json_t *auth_methods;
2569  json_t *sig_algs;
2570  json_t *scopes;
2571  json_t *response_types;
2572  json_t *sub_types;
2573  json_t *claim_types;
2574  char *oidc_config_str;
2575  struct MHD_Response *resp;
2576  struct RequestHandle *handle = cls;
2577 
2578  oidc_config = json_object ();
2579  // FIXME get from config?
2580  json_object_set_new (oidc_config,
2581  "issuer", json_string ("http://localhost:7776"));
2582  json_object_set_new (oidc_config,
2583  "authorization_endpoint",
2584  json_string ("https://api.reclaim/openid/authorize"));
2585  json_object_set_new (oidc_config,
2586  "token_endpoint",
2587  json_string ("http://localhost:7776/openid/token"));
2588  auth_methods = json_array ();
2589  json_array_append_new (auth_methods,
2590  json_string ("client_secret_basic"));
2591  json_array_append_new (auth_methods,
2592  json_string ("client_secret_post"));
2593  json_object_set_new (oidc_config,
2594  "token_endpoint_auth_methods_supported",
2595  auth_methods);
2596  sig_algs = json_array ();
2597  json_array_append_new (sig_algs,
2598  json_string ("HS512"));
2599  json_object_set_new (oidc_config,
2600  "id_token_signing_alg_values_supported",
2601  sig_algs);
2602  json_object_set_new (oidc_config,
2603  "userinfo_endpoint",
2604  json_string ("http://localhost:7776/openid/userinfo"));
2605  scopes = json_array ();
2606  json_array_append_new (scopes,
2607  json_string ("openid"));
2608  json_array_append_new (scopes,
2609  json_string ("profile"));
2610  json_array_append_new (scopes,
2611  json_string ("email"));
2612  json_array_append_new (scopes,
2613  json_string ("address"));
2614  json_array_append_new (scopes,
2615  json_string ("phone"));
2616  json_object_set_new (oidc_config,
2617  "scopes_supported",
2618  scopes);
2619  response_types = json_array ();
2620  json_array_append_new (response_types,
2621  json_string ("code"));
2622  json_object_set_new (oidc_config,
2623  "response_types_supported",
2624  response_types);
2625  sub_types = json_array ();
2626  json_array_append_new (sub_types,
2627  json_string ("public")); /* no pairwise suppport */
2628  json_object_set_new (oidc_config,
2629  "subject_types_supported",
2630  sub_types);
2631  claim_types = json_array ();
2632  json_array_append_new (claim_types,
2633  json_string ("normal"));
2634  json_array_append_new (claim_types,
2635  json_string ("aggregated"));
2636  json_object_set_new (oidc_config,
2637  "claim_types_supported",
2638  claim_types);
2639  json_object_set_new (oidc_config,
2640  "claims_parameter_supported",
2641  json_boolean (1));
2642  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2643  resp = GNUNET_REST_create_response (oidc_config_str);
2644  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2645  json_decref (oidc_config);
2646  GNUNET_free (oidc_config_str);
2647  cleanup_handle (handle);
2648 }
2649 
2650 
2658 static void
2660  const char *url,
2661  void *cls)
2662 {
2663  struct MHD_Response *resp;
2664  struct RequestHandle *handle = cls;
2665 
2666  // For now, independent of path return all options
2667  resp = GNUNET_REST_create_response (NULL);
2668  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
2669  MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
2670  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2671  cleanup_handle (handle);
2672  return;
2673 }
2674 
2675 
2676 static enum GNUNET_GenericReturnValue
2679  void *proc_cls)
2680 {
2681  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2683  static const struct GNUNET_REST_RequestHandler handlers[] =
2684  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2685  { MHD_HTTP_METHOD_POST,
2686  GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2687  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2688  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2689  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2690  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2691  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2693  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2694  &oidc_config_cors },
2695  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2697 
2698  handle->oidc = GNUNET_new (struct OIDC_Variables);
2699  if (NULL == OIDC_cookie_jar_map)
2700  OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2701  GNUNET_NO);
2702  if (NULL == oidc_code_cache)
2703  oidc_code_cache = GNUNET_CONTAINER_multihashmap_create (10,
2704  GNUNET_NO);
2705 
2706  handle->response_code = 0;
2708  handle->proc_cls = proc_cls;
2709  handle->proc = proc;
2710  handle->rest_handle = rest_handle;
2711  handle->url = GNUNET_strdup (rest_handle->url);
2712  handle->timeout_task =
2713  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2714  GNUNET_CONTAINER_DLL_insert (requests_head,
2715  requests_tail,
2716  handle);
2717  if (handle->url[strlen (handle->url) - 1] == '/')
2718  handle->url[strlen (handle->url) - 1] = '\0';
2719  if (GNUNET_NO ==
2720  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2721  return GNUNET_NO;
2722 
2723  return GNUNET_YES;
2724 }
2725 
2726 
2733 void *
2735 {
2736  static struct Plugin plugin;
2737  struct GNUNET_REST_Plugin *api;
2738 
2739  cfg = cls;
2740  if (NULL != plugin.cfg)
2741  return NULL; /* can only initialize once! */
2742  memset (&plugin, 0, sizeof(struct Plugin));
2743  plugin.cfg = cfg;
2744  api = GNUNET_new (struct GNUNET_REST_Plugin);
2745  api->cls = &plugin;
2748  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2749  gns_handle = GNUNET_GNS_connect (cfg);
2750  idp = GNUNET_RECLAIM_connect (cfg);
2751 
2754  "%s, %s, %s, %s, %s",
2755  MHD_HTTP_METHOD_GET,
2756  MHD_HTTP_METHOD_POST,
2757  MHD_HTTP_METHOD_PUT,
2758  MHD_HTTP_METHOD_DELETE,
2759  MHD_HTTP_METHOD_OPTIONS);
2760 
2762  _ ("OpenID Connect REST API initialized\n"));
2763  return api;
2764 }
2765 
2766 
2767 static int
2768 cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2769 {
2770  GNUNET_free (value);
2771  return GNUNET_YES;
2772 }
2773 
2774 
2781 void *
2783 {
2784  struct GNUNET_REST_Plugin *api = cls;
2785  struct Plugin *plugin = api->cls;
2786  struct EgoEntry *ego_entry;
2787 
2788  plugin->cfg = NULL;
2789  while (NULL != requests_head)
2790  cleanup_handle (requests_head);
2791  if (NULL != OIDC_cookie_jar_map)
2792  {
2793  GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2794  &cleanup_hashmap,
2795  NULL);
2796  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2797  }
2798  if (NULL != oidc_code_cache)
2799  {
2800  GNUNET_CONTAINER_multihashmap_iterate (oidc_code_cache,
2801  &cleanup_hashmap,
2802  NULL);
2803  GNUNET_CONTAINER_multihashmap_destroy (oidc_code_cache);
2804  }
2805 
2807  if (NULL != gns_handle)
2808  GNUNET_GNS_disconnect (gns_handle);
2809  if (NULL != identity_handle)
2810  GNUNET_IDENTITY_disconnect (identity_handle);
2811  if (NULL != idp)
2813  while (NULL != (ego_entry = ego_head))
2814  {
2815  GNUNET_CONTAINER_DLL_remove (ego_head,
2816  ego_tail,
2817  ego_entry);
2818  GNUNET_free (ego_entry->identifier);
2819  GNUNET_free (ego_entry->keystring);
2820  GNUNET_free (ego_entry);
2821  }
2822  GNUNET_free (api);
2824  "OpenID Connect REST plugin is finished\n");
2825  return NULL;
2826 }
2827 
2828 
2829 /* 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:1487
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: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.
#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: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
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: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: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.
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:860
#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: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: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: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: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.
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: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: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.
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.
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: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
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: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: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: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: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.