2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
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.
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.
17 * @file identity-provider/jwt.c
18 * @brief helper library for JSON-Web-Tokens
19 * @author Martin Schanzenbach
22 #include "gnunet_util_lib.h"
23 #include "gnunet_signatures.h"
24 #include "gnunet_identity_attribute_lib.h"
30 /*TODO is this the correct way to define new algs? */
31 #define JWT_ALG_VALUE "urn:org:gnunet:jwt:alg:ecdsa:ed25519"
35 #define JWT_TYP_VALUE "jwt"
37 //TODO change server address
38 #define SERVER_ADDRESS "https://localhost"
41 create_jwt_header(void)
46 root = json_object ();
47 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
48 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
50 json_str = json_dumps (root, JSON_INDENT(1));
56 * Create a JWT from attributes
58 * @param aud_key the public of the subject
59 * @param attrs the attribute list
60 * @param priv_key the key used to sign the JWT
61 * @return a new base64-encoded JWT string.
64 jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
65 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
66 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key)
68 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
69 struct GNUNET_CRYPTO_EcdsaPublicKey sub_key;
70 struct GNUNET_CRYPTO_EcdsaSignature signature;
71 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
80 char* signature_target;
81 char* signature_base64;
85 //exp REQUIRED time expired from config
86 //iat REQUIRED time now
87 //auth_time only if max_age
89 // OPTIONAL acr,amr,azp
90 GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &sub_key);
91 /* TODO maybe we should use a local identity here */
92 subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key,
93 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
94 audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
95 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
96 header = create_jwt_header ();
97 body = json_object ();
98 /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */
99 //iss REQUIRED case sensitive server uri with https
100 json_object_set_new (body,
101 "iss", json_string (SERVER_ADDRESS));
102 //sub REQUIRED public key identity, not exceed 255 ASCII length
103 json_object_set_new (body,
104 "sub", json_string (subject));
105 /* TODO what should be in here exactly? */
106 //aud REQUIRED public key client_id must be there
107 json_object_set_new (body,
108 "aud", json_string (audience));
109 for (le = attrs->list_head; NULL != le; le = le->next)
112 * TODO here we should have a function that
113 * calls the Attribute plugins to create a
114 * json representation for its value
116 attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type,
118 le->claim->data_size);
119 json_object_set_new (body,
121 json_string (attr_val_str));
122 GNUNET_free (attr_val_str);
124 body_str = json_dumps (body, JSON_INDENT(0));
127 GNUNET_STRINGS_base64_encode (header,
130 //Remove GNUNET padding of base64
131 padding = strtok(header_base64, "=");
132 while (NULL != padding)
133 padding = strtok(NULL, "=");
135 GNUNET_STRINGS_base64_encode (body_str,
139 //Remove GNUNET padding of base64
140 padding = strtok(body_base64, "=");
141 while (NULL != padding)
142 padding = strtok(NULL, "=");
144 GNUNET_free (subject);
145 GNUNET_free (audience);
149 * Creating the JWT signature. This might not be
150 * standards compliant, check.
152 GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64);
155 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
156 strlen (signature_target));
158 htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
159 purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
160 GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
161 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
163 (struct GNUNET_CRYPTO_EcdsaSignature *)&signature))
165 GNUNET_free (signature_target);
166 GNUNET_free (body_str);
167 GNUNET_free (body_base64);
168 GNUNET_free (header_base64);
169 GNUNET_free (purpose);
172 GNUNET_STRINGS_base64_encode ((const char*)&signature,
173 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
175 GNUNET_asprintf (&result, "%s.%s.%s",
176 header_base64, body_base64, signature_base64);
178 GNUNET_free (signature_target);
179 GNUNET_free (header);
180 GNUNET_free (body_str);
181 GNUNET_free (signature_base64);
182 GNUNET_free (body_base64);
183 GNUNET_free (header_base64);
184 GNUNET_free (purpose);