aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2019-04-26 14:47:29 +0200
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2019-04-26 14:47:29 +0200
commitdba51d34726695de64bca656399ed8f82d225f53 (patch)
treead64981fb7189fe0c12b3e6c7f7f819bfe4d700a /src
parentb6d8d75ac3700abee64adb452b7e3652b75933c0 (diff)
downloadgnunet-dba51d34726695de64bca656399ed8f82d225f53.tar.gz
gnunet-dba51d34726695de64bca656399ed8f82d225f53.zip
RECLAIM/REST: simplify auth code; include attrs
Diffstat (limited to 'src')
-rw-r--r--src/reclaim/oidc_helper.c311
-rw-r--r--src/reclaim/oidc_helper.h8
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c49
3 files changed, 195 insertions, 173 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 331bd2711..37387b5e0 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -52,7 +52,8 @@ static void
52replace_char (char *str, char find, char replace) 52replace_char (char *str, char find, char replace)
53{ 53{
54 char *current_pos = strchr (str, find); 54 char *current_pos = strchr (str, find);
55 while (current_pos) { 55 while (current_pos)
56 {
56 *current_pos = replace; 57 *current_pos = replace;
57 current_pos = strchr (current_pos, find); 58 current_pos = strchr (current_pos, find);
58 } 59 }
@@ -84,7 +85,8 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
84 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 85 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
85 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, 86 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
86 const struct GNUNET_TIME_Relative *expiration_time, 87 const struct GNUNET_TIME_Relative *expiration_time,
87 const char *nonce, const char *secret_key) 88 const char *nonce,
89 const char *secret_key)
88{ 90{
89 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; 91 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
90 struct GNUNET_HashCode signature; 92 struct GNUNET_HashCode signature;
@@ -110,9 +112,11 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
110 // nonce only if nonce 112 // nonce only if nonce
111 // OPTIONAL acr,amr,azp 113 // OPTIONAL acr,amr,azp
112 subject = GNUNET_STRINGS_data_to_string_alloc ( 114 subject = GNUNET_STRINGS_data_to_string_alloc (
113 sub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 115 sub_key,
116 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
114 audience = GNUNET_STRINGS_data_to_string_alloc ( 117 audience = GNUNET_STRINGS_data_to_string_alloc (
115 aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 118 aud_key,
119 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
116 header = create_jwt_header (); 120 header = create_jwt_header ();
117 body = json_object (); 121 body = json_object ();
118 122
@@ -125,21 +129,27 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
125 // aud REQUIRED public key client_id must be there 129 // aud REQUIRED public key client_id must be there
126 json_object_set_new (body, "aud", json_string (audience)); 130 json_object_set_new (body, "aud", json_string (audience));
127 // iat 131 // iat
128 json_object_set_new (body, "iat", 132 json_object_set_new (body,
133 "iat",
129 json_integer (time_now.abs_value_us / (1000 * 1000))); 134 json_integer (time_now.abs_value_us / (1000 * 1000)));
130 // exp 135 // exp
131 json_object_set_new (body, "exp", 136 json_object_set_new (body,
137 "exp",
132 json_integer (exp_time.abs_value_us / (1000 * 1000))); 138 json_integer (exp_time.abs_value_us / (1000 * 1000)));
133 // nbf 139 // nbf
134 json_object_set_new (body, "nbf", 140 json_object_set_new (body,
141 "nbf",
135 json_integer (time_now.abs_value_us / (1000 * 1000))); 142 json_integer (time_now.abs_value_us / (1000 * 1000)));
136 // nonce 143 // nonce
137 if (NULL != nonce) 144 if (NULL != nonce)
138 json_object_set_new (body, "nonce", json_string (nonce)); 145 json_object_set_new (body, "nonce", json_string (nonce));
139 146
140 for (le = attrs->list_head; NULL != le; le = le->next) { 147 for (le = attrs->list_head; NULL != le; le = le->next)
141 attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string ( 148 {
142 le->claim->type, le->claim->data, le->claim->data_size); 149 attr_val_str =
150 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
151 le->claim->data,
152 le->claim->data_size);
143 json_object_set_new (body, le->claim->name, json_string (attr_val_str)); 153 json_object_set_new (body, le->claim->name, json_string (attr_val_str));
144 GNUNET_free (attr_val_str); 154 GNUNET_free (attr_val_str);
145 } 155 }
@@ -160,14 +170,20 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
160 * standards compliant, check. 170 * standards compliant, check.
161 */ 171 */
162 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64); 172 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
163 GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, 173 GNUNET_CRYPTO_hmac_raw (secret_key,
164 strlen (signature_target), &signature); 174 strlen (secret_key),
165 GNUNET_STRINGS_base64_encode ((const char *)&signature, 175 signature_target,
176 strlen (signature_target),
177 &signature);
178 GNUNET_STRINGS_base64_encode ((const char *) &signature,
166 sizeof (struct GNUNET_HashCode), 179 sizeof (struct GNUNET_HashCode),
167 &signature_base64); 180 &signature_base64);
168 fix_base64 (signature_base64); 181 fix_base64 (signature_base64);
169 182
170 GNUNET_asprintf (&result, "%s.%s.%s", header_base64, body_base64, 183 GNUNET_asprintf (&result,
184 "%s.%s.%s",
185 header_base64,
186 body_base64,
171 signature_base64); 187 signature_base64);
172 188
173 GNUNET_free (signature_target); 189 GNUNET_free (signature_target);
@@ -178,64 +194,125 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
178 GNUNET_free (header_base64); 194 GNUNET_free (header_base64);
179 return result; 195 return result;
180} 196}
197
198
199/**
200 * Returns base64 encoded string urlencoded
201 *
202 * @param string the string to encode
203 * @return base64 encoded string
204 */
205static char *
206base64_encode (const char *data,
207 size_t data_size)
208{
209 char *enc;
210 char *enc_urlencode;
211 char *tmp;
212 int i;
213 int num_pads = 0;
214
215 GNUNET_STRINGS_base64_encode (data, data_size, &enc);
216 tmp = strchr (enc, '=');
217 num_pads = strlen (enc) - (tmp - enc);
218 GNUNET_assert ((3 > num_pads) && (0 <= num_pads));
219 if (0 == num_pads)
220 return enc;
221 enc_urlencode = GNUNET_malloc (strlen (enc) + num_pads * 2);
222 strcpy (enc_urlencode, enc);
223 GNUNET_free (enc);
224 tmp = strchr (enc_urlencode, '=');
225 for (i = 0; i < num_pads; i++) {
226 strcpy (tmp, "%3D"); // replace '=' with '%3D'
227 tmp += 3;
228 }
229 return enc_urlencode;
230}
231
232
233
234
181/** 235/**
182 * Builds an OIDC authorization code including 236 * Builds an OIDC authorization code including
183 * a reclaim ticket and nonce 237 * a reclaim ticket and nonce
184 * 238 *
185 * @param issuer the issuer of the ticket, used to sign the ticket and nonce 239 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
186 * @param ticket the ticket to include in the code 240 * @param ticket the ticket to include in the code
241 * @param attrs list of attributes whicha re shared
187 * @param nonce the nonce to include in the code 242 * @param nonce the nonce to include in the code
188 * @return a new authorization code (caller must free) 243 * @return a new authorization code (caller must free)
189 */ 244 */
190char * 245char *
191OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, 246OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
192 const struct GNUNET_RECLAIM_Ticket *ticket, 247 const struct GNUNET_RECLAIM_Ticket *ticket,
193 const char *nonce) 248 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
249 const char *nonce_str)
194{ 250{
195 char *ticket_str; 251 char *code_payload;
196 json_t *code_json; 252 char *attrs_ser;
197 char *signature_payload; 253 char *code_str;
198 char *signature_str; 254 char *buf_ptr;
199 char *authz_code;
200 size_t signature_payload_len; 255 size_t signature_payload_len;
256 size_t attr_list_len;
257 size_t code_payload_len;
258 unsigned int nonce;
259 unsigned int nonce_tmp;
201 struct GNUNET_CRYPTO_EcdsaSignature signature; 260 struct GNUNET_CRYPTO_EcdsaSignature signature;
202 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 261 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
203 262
204 signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); 263 attrs_ser = NULL;
205 if (NULL != nonce) 264 signature_payload_len =
206 signature_payload_len += strlen (nonce); 265 sizeof (struct GNUNET_RECLAIM_Ticket) + sizeof (unsigned int);
207 266 if (NULL != attrs)
208 signature_payload = 267 {
209 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 268 attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
210 signature_payload_len); 269 signature_payload_len += attr_list_len;
211 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; 270 attrs_ser = GNUNET_malloc (attr_list_len);
271 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, attrs_ser);
272 }
273 code_payload_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
274 signature_payload_len + sizeof (signature);
275 code_payload = GNUNET_malloc (code_payload_len);
276 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
212 purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 277 purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
213 signature_payload_len); 278 signature_payload_len);
214 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); 279 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
215 memcpy (&purpose[1], ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); 280 // First, copy ticket
216 if (NULL != nonce) 281 buf_ptr = (char *) &purpose[1];
217 memcpy (((char *)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket), 282 memcpy (buf_ptr, ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
218 nonce, strlen (nonce)); 283 buf_ptr += sizeof (struct GNUNET_RECLAIM_Ticket);
219 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, purpose, &signature)) { 284 // Then copy nonce
220 GNUNET_free (signature_payload); 285 nonce = 0;
286 if (NULL != nonce_str)
287 {
288 if ((1 != SSCANF (nonce_str, "%u", &nonce)) || (nonce > UINT16_MAX))
289 {
290 GNUNET_free (code_payload);
291 GNUNET_free_non_null (attrs_ser);
292 return NULL;
293 }
294 }
295 nonce_tmp = htons (nonce);
296 memcpy (buf_ptr, &nonce_tmp, sizeof (unsigned int));
297 buf_ptr += sizeof (unsigned int);
298 // Finally, attributes
299 if (NULL != attrs_ser)
300 {
301 memcpy (buf_ptr, attrs_ser, attr_list_len);
302 buf_ptr += attr_list_len;
303 }
304 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, purpose, &signature))
305 {
306 GNUNET_free (code_payload);
307 GNUNET_free_non_null (attrs_ser);
221 return NULL; 308 return NULL;
222 } 309 }
223 signature_str = 310 memcpy (buf_ptr, &signature, sizeof (signature));
224 GNUNET_STRINGS_data_to_string_alloc (&signature, sizeof (signature)); 311 code_str = base64_encode ((const char *) &code_payload,
225 ticket_str = GNUNET_STRINGS_data_to_string_alloc ( 312 code_payload_len);
226 ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); 313 GNUNET_free (code_payload);
227 314 GNUNET_free_non_null (attrs_ser);
228 code_json = json_object (); 315 return code_str;
229 json_object_set_new (code_json, "ticket", json_string (ticket_str));
230 if (NULL != nonce)
231 json_object_set_new (code_json, "nonce", json_string (nonce));
232 json_object_set_new (code_json, "signature", json_string (signature_str));
233 authz_code = json_dumps (code_json, JSON_INDENT (0) | JSON_COMPACT);
234 GNUNET_free (signature_payload);
235 GNUNET_free (signature_str);
236 GNUNET_free (ticket_str);
237 json_decref (code_json);
238 return authz_code;
239} 316}
240 317
241 318
@@ -247,99 +324,70 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
247 * @param audience the expected audience of the code 324 * @param audience the expected audience of the code
248 * @param code the string representation of the code 325 * @param code the string representation of the code
249 * @param ticket where to store the ticket 326 * @param ticket where to store the ticket
327 * @param attrs the attributes in the code
250 * @param nonce where to store the nonce 328 * @param nonce where to store the nonce
251 * @return GNUNET_OK if successful, else GNUNET_SYSERR 329 * @return GNUNET_OK if successful, else GNUNET_SYSERR
252 */ 330 */
253int 331int
254OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, 332OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
255 const char *code, struct GNUNET_RECLAIM_Ticket **ticket, 333 const char *code,
256 char **nonce) 334 struct GNUNET_RECLAIM_Ticket *ticket,
335 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs,
336 char **nonce_str)
257{ 337{
258 json_error_t error; 338 char *code_payload;
259 json_t *code_json; 339 char *attrs_ser;
260 json_t *ticket_json; 340 char *ptr;
261 json_t *nonce_json;
262 json_t *signature_json;
263 const char *ticket_str;
264 const char *signature_str;
265 const char *nonce_str;
266 char *code_output;
267 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 341 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
268 struct GNUNET_CRYPTO_EcdsaSignature signature; 342 struct GNUNET_CRYPTO_EcdsaSignature *signature;
269 size_t signature_payload_len; 343 size_t code_payload_len;
270 344 size_t attrs_ser_len;
271 code_output = NULL; 345 size_t signature_offset;
272 GNUNET_STRINGS_base64_decode (code, strlen (code), (void **)&code_output); 346 unsigned int nonce;
273 code_json = json_loads (code_output, 0, &error); 347
274 GNUNET_free (code_output); 348 code_payload = NULL;
275 ticket_json = json_object_get (code_json, "ticket"); 349 code_payload_len =
276 nonce_json = json_object_get (code_json, "nonce"); 350 GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload);
277 signature_json = json_object_get (code_json, "signature"); 351 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
278 *ticket = NULL; 352 attrs_ser_len = code_payload_len;
279 *nonce = NULL; 353 attrs_ser_len -= sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose);
280 354 *ticket = *((struct GNUNET_RECLAIM_Ticket*) &purpose[1]);
281 if ((NULL == ticket_json || !json_is_string (ticket_json)) || 355 attrs_ser_len -= sizeof (struct GNUNET_RECLAIM_Ticket);
282 (NULL == signature_json || !json_is_string (signature_json))) { 356 nonce = ntohs (((unsigned int *) &ticket[1]));
283 json_decref (code_json); 357 attrs_ser_len -= sizeof (unsigned int);
284 return GNUNET_SYSERR; 358 ptr = code_payload;
285 } 359 signature_offset =
286 ticket_str = json_string_value (ticket_json); 360 code_payload_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
287 signature_str = json_string_value (signature_json); 361 signature = (struct GNUNET_CRYPTO_EcdsaSignature *)&ptr[signature_offset];
288 nonce_str = NULL; 362 attrs_ser_len -= sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
289 if (NULL != nonce_json) 363 attrs_ser = ((char *) &ticket[1]) + sizeof (unsigned int);
290 nonce_str = json_string_value (nonce_json); 364 *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, attrs_ser_len);
291 signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); 365 if (0 != GNUNET_memcmp (audience, &ticket->audience))
292 if (NULL != nonce_str) 366 {
293 signature_payload_len += strlen (nonce_str); 367 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (*attrs);
294 purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 368 GNUNET_free (code_payload);
295 signature_payload_len);
296 purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
297 signature_payload_len);
298 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
299 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (
300 ticket_str, strlen (ticket_str), &purpose[1],
301 sizeof (struct GNUNET_RECLAIM_Ticket))) {
302 GNUNET_free (purpose);
303 json_decref (code_json);
304 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot parse ticket!\n");
305 return GNUNET_SYSERR;
306 }
307 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (
308 signature_str, strlen (signature_str), &signature,
309 sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) {
310 GNUNET_free (purpose);
311 json_decref (code_json);
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot parse signature!\n");
313 return GNUNET_SYSERR;
314 }
315 *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
316 memcpy (*ticket, &purpose[1], sizeof (struct GNUNET_RECLAIM_Ticket));
317 if (0 != GNUNET_memcmp (audience, &(*ticket)->audience)) {
318 GNUNET_free (purpose);
319 GNUNET_free (*ticket);
320 json_decref (code_json);
321 *ticket = NULL;
322 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
323 "Audience in ticket does not match client!\n"); 370 "Audience in ticket does not match client!\n");
324 return GNUNET_SYSERR; 371 return GNUNET_SYSERR;
325 } 372 }
326 if (NULL != nonce_str)
327 memcpy (((char *)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
328 nonce_str, strlen (nonce_str));
329 if (GNUNET_OK != 373 if (GNUNET_OK !=
330 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, 374 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
331 purpose, &signature, &(*ticket)->identity)) { 375 purpose,
332 GNUNET_free (purpose); 376 signature,
333 GNUNET_free (*ticket); 377 &ticket->identity))
334 json_decref (code_json); 378 {
335 *ticket = NULL; 379 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (*attrs);
336 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of authZ code invalid!\n"); 380 GNUNET_free (code_payload);
381 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
337 return GNUNET_SYSERR; 382 return GNUNET_SYSERR;
338 } 383 }
339 *nonce = GNUNET_strdup (nonce_str); 384 *nonce_str = NULL;
385 if (nonce != 0)
386 GNUNET_asprintf (nonce_str, "%u", nonce);
340 return GNUNET_OK; 387 return GNUNET_OK;
341} 388}
342 389
390
343/** 391/**
344 * Build a token response for a token request 392 * Build a token response for a token request
345 * TODO: Maybe we should add the scope here? 393 * TODO: Maybe we should add the scope here?
@@ -350,7 +398,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
350 * @param token_response where to store the response 398 * @param token_response where to store the response
351 */ 399 */
352void 400void
353OIDC_build_token_response (const char *access_token, const char *id_token, 401OIDC_build_token_response (const char *access_token,
402 const char *id_token,
354 const struct GNUNET_TIME_Relative *expiration_time, 403 const struct GNUNET_TIME_Relative *expiration_time,
355 char **token_response) 404 char **token_response)
356{ 405{
@@ -364,8 +413,9 @@ OIDC_build_token_response (const char *access_token, const char *id_token,
364 json_object_set_new (root_json, "access_token", json_string (access_token)); 413 json_object_set_new (root_json, "access_token", json_string (access_token));
365 json_object_set_new (root_json, "token_type", json_string ("Bearer")); 414 json_object_set_new (root_json, "token_type", json_string ("Bearer"));
366 json_object_set_new ( 415 json_object_set_new (
367 root_json, "expires_in", 416 root_json,
368 json_integer (expiration_time->rel_value_us / (1000 * 1000))); 417 "expires_in",
418 json_integer (expiration_time->rel_value_us / (1000 * 1000)));
369 json_object_set_new (root_json, "id_token", json_string (id_token)); 419 json_object_set_new (root_json, "id_token", json_string (id_token));
370 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT); 420 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
371 json_decref (root_json); 421 json_decref (root_json);
@@ -382,9 +432,10 @@ OIDC_access_token_new ()
382 uint64_t random_number; 432 uint64_t random_number;
383 433
384 random_number = 434 random_number =
385 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); 435 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
386 GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number); 436 GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number);
387 GNUNET_STRINGS_base64_encode (access_token_number, 437 GNUNET_STRINGS_base64_encode (access_token_number,
388 strlen (access_token_number), &access_token); 438 strlen (access_token_number),
439 &access_token);
389 return access_token; 440 return access_token;
390} 441}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index d718b7a78..3c57dc235 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -11,7 +11,7 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
@@ -62,12 +62,14 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
62 * 62 *
63 * @param issuer the issuer of the ticket, used to sign the ticket and nonce 63 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
64 * @param ticket the ticket to include in the code 64 * @param ticket the ticket to include in the code
65 * @param attrs list of attributes to share
65 * @param nonce the nonce to include in the code 66 * @param nonce the nonce to include in the code
66 * @return a new authorization code (caller must free) 67 * @return a new authorization code (caller must free)
67 */ 68 */
68char* 69char*
69OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, 70OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
70 const struct GNUNET_RECLAIM_Ticket *ticket, 71 const struct GNUNET_RECLAIM_Ticket *ticket,
72 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
71 const char* nonce); 73 const char* nonce);
72 74
73/** 75/**
@@ -78,13 +80,15 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
78 * @param audience the expected audience of the code 80 * @param audience the expected audience of the code
79 * @param code the string representation of the code 81 * @param code the string representation of the code
80 * @param ticket where to store the ticket 82 * @param ticket where to store the ticket
83 * @param attrs the attributes found in the code
81 * @param nonce where to store the nonce 84 * @param nonce where to store the nonce
82 * @return GNUNET_OK if successful, else GNUNET_SYSERR 85 * @return GNUNET_OK if successful, else GNUNET_SYSERR
83 */ 86 */
84int 87int
85OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, 88OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
86 const char* code, 89 const char* code,
87 struct GNUNET_RECLAIM_Ticket **ticket, 90 struct GNUNET_RECLAIM_Ticket *ticket,
91 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs,
88 char **nonce); 92 char **nonce);
89 93
90/** 94/**
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 6cf1ffdee..07cb55d79 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -676,37 +676,6 @@ return_userinfo_response (void *cls)
676 cleanup_handle (handle); 676 cleanup_handle (handle);
677} 677}
678 678
679/**
680 * Returns base64 encoded string urlencoded
681 *
682 * @param string the string to encode
683 * @return base64 encoded string
684 */
685static char *
686base64_encode (const char *s)
687{
688 char *enc;
689 char *enc_urlencode;
690 char *tmp;
691 int i;
692 int num_pads = 0;
693
694 GNUNET_STRINGS_base64_encode (s, strlen (s), &enc);
695 tmp = strchr (enc, '=');
696 num_pads = strlen (enc) - (tmp - enc);
697 GNUNET_assert ((3 > num_pads) && (0 <= num_pads));
698 if (0 == num_pads)
699 return enc;
700 enc_urlencode = GNUNET_malloc (strlen (enc) + num_pads * 2);
701 strcpy (enc_urlencode, enc);
702 GNUNET_free (enc);
703 tmp = strchr (enc_urlencode, '=');
704 for (i = 0; i < num_pads; i++) {
705 strcpy (tmp, "%3D"); // replace '=' with '%3D'
706 tmp += 3;
707 }
708 return enc_urlencode;
709}
710 679
711/** 680/**
712 * Respond to OPTIONS request 681 * Respond to OPTIONS request
@@ -870,8 +839,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
870 struct MHD_Response *resp; 839 struct MHD_Response *resp;
871 char *ticket_str; 840 char *ticket_str;
872 char *redirect_uri; 841 char *redirect_uri;
873 char *code_json_string; 842 char *code_string;
874 char *code_base64_final_string;
875 843
876 handle->idp_op = NULL; 844 handle->idp_op = NULL;
877 handle->ticket = *ticket; 845 handle->ticket = *ticket;
@@ -884,20 +852,20 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
884 ticket_str = GNUNET_STRINGS_data_to_string_alloc ( 852 ticket_str = GNUNET_STRINGS_data_to_string_alloc (
885 &handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); 853 &handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
886 // TODO change if more attributes are needed (see max_age) 854 // TODO change if more attributes are needed (see max_age)
887 code_json_string = OIDC_build_authz_code (&handle->priv_key, &handle->ticket, 855 code_string = OIDC_build_authz_code (&handle->priv_key, &handle->ticket,
856 handle->attr_list,
888 handle->oidc->nonce); 857 handle->oidc->nonce);
889 code_base64_final_string = base64_encode (code_json_string);
890 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) && 858 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
891 (NULL != handle->tld)) { 859 (NULL != handle->tld)) {
892 860
893 GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", 861 GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
894 handle->redirect_prefix, handle->tld, 862 handle->redirect_prefix, handle->tld,
895 handle->redirect_suffix, handle->oidc->response_type, 863 handle->redirect_suffix, handle->oidc->response_type,
896 code_base64_final_string, handle->oidc->state); 864 code_string, handle->oidc->state);
897 } else { 865 } else {
898 GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s", 866 GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s",
899 handle->oidc->redirect_uri, handle->oidc->response_type, 867 handle->oidc->redirect_uri, handle->oidc->response_type,
900 code_base64_final_string, handle->oidc->state); 868 code_string, handle->oidc->state);
901 } 869 }
902 resp = GNUNET_REST_create_response (""); 870 resp = GNUNET_REST_create_response ("");
903 MHD_add_response_header (resp, "Location", redirect_uri); 871 MHD_add_response_header (resp, "Location", redirect_uri);
@@ -905,8 +873,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
905 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 873 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
906 GNUNET_free (redirect_uri); 874 GNUNET_free (redirect_uri);
907 GNUNET_free (ticket_str); 875 GNUNET_free (ticket_str);
908 GNUNET_free (code_json_string); 876 GNUNET_free (code_string);
909 GNUNET_free (code_base64_final_string);
910} 877}
911 878
912static void 879static void
@@ -1653,7 +1620,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url,
1653 } 1620 }
1654 1621
1655 // decode code 1622 // decode code
1656 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, &ticket, &nonce)) { 1623 ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
1624 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, ticket, &cl, &nonce)) {
1657 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); 1625 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
1658 handle->edesc = GNUNET_strdup ("invalid code"); 1626 handle->edesc = GNUNET_strdup ("invalid code");
1659 handle->response_code = MHD_HTTP_BAD_REQUEST; 1627 handle->response_code = MHD_HTTP_BAD_REQUEST;
@@ -1692,7 +1660,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url,
1692 return; 1660 return;
1693 } 1661 }
1694 // TODO We should collect the attributes here. cl always empty 1662 // TODO We should collect the attributes here. cl always empty
1695 cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
1696 id_token = OIDC_id_token_new (&ticket->audience, &ticket->identity, cl, 1663 id_token = OIDC_id_token_new (&ticket->audience, &ticket->identity, cl,
1697 &expiration_time, 1664 &expiration_time,
1698 (NULL != nonce) ? nonce : NULL, jwt_secret); 1665 (NULL != nonce) ? nonce : NULL, jwt_secret);