4#ifndef JWT_DISABLE_PICOJSON
5#ifndef PICOJSON_USE_INT64
6#define PICOJSON_USE_INT64
8#include "goby/util/thirdparty/jwt-cpp/picojson/picojson.h"
11#ifndef JWT_DISABLE_BASE64
15#include <openssl/ec.h>
16#include <openssl/ecdsa.h>
17#include <openssl/err.h>
18#include <openssl/evp.h>
19#include <openssl/hmac.h>
20#include <openssl/pem.h>
21#include <openssl/ssl.h>
31#include <system_error>
33#include <unordered_map>
37#if __cplusplus >= 201402L
39#if __has_include(<experimental/type_traits>)
40#include <experimental/type_traits>
45#if OPENSSL_VERSION_NUMBER >= 0x30000000L
46#define JWT_OPENSSL_3_0
47#elif OPENSSL_VERSION_NUMBER >= 0x10101000L
48#define JWT_OPENSSL_1_1_1
49#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
50#define JWT_OPENSSL_1_1_0
51#elif OPENSSL_VERSION_NUMBER >= 0x10000000L
52#define JWT_OPENSSL_1_0_0
55#if defined(LIBRESSL_VERSION_NUMBER)
56#define JWT_OPENSSL_1_0_0
59#if defined(LIBWOLFSSL_VERSION_HEX)
60#define JWT_OPENSSL_1_1_1
63#ifndef JWT_CLAIM_EXPLICIT
64#define JWT_CLAIM_EXPLICIT explicit
79using date = std::chrono::system_clock::time_point;
88 using system_error::system_error;
92 using system_error::system_error;
96 using system_error::system_error;
100 using system_error::system_error;
104 using system_error::system_error;
127 class rsa_error_cat :
public std::error_category
130 const char* name()
const noexcept override {
return "rsa_error"; };
131 std::string message(
int ev)
const override
135 case rsa_error::ok:
return "no error";
136 case rsa_error::cert_load_failed:
return "error loading cert into memory";
137 case rsa_error::get_key_failed:
return "error getting key from certificate";
138 case rsa_error::write_key_failed:
return "error writing key data in PEM format";
139 case rsa_error::write_cert_failed:
return "error writing cert data in PEM format";
140 case rsa_error::convert_to_pem_failed:
return "failed to convert key to pem";
141 case rsa_error::load_key_bio_write:
return "failed to load key: bio write failed";
142 case rsa_error::load_key_bio_read:
return "failed to load key: bio read failed";
143 case rsa_error::create_mem_bio_failed:
return "failed to create memory bio";
144 case rsa_error::no_key_provided:
145 return "at least one of public or private key need to be present";
146 default:
return "unknown RSA error";
150 static rsa_error_cat cat;
177 class ecdsa_error_cat :
public std::error_category
180 const char* name()
const noexcept override {
return "ecdsa_error"; };
181 std::string message(
int ev)
const override
185 case ecdsa_error::ok:
return "no error";
186 case ecdsa_error::load_key_bio_write:
return "failed to load key: bio write failed";
187 case ecdsa_error::load_key_bio_read:
return "failed to load key: bio read failed";
188 case ecdsa_error::create_mem_bio_failed:
return "failed to create memory bio";
189 case ecdsa_error::no_key_provided:
190 return "at least one of public or private key need to be present";
191 case ecdsa_error::invalid_key_size:
return "invalid key size";
192 case ecdsa_error::invalid_key:
return "invalid key";
193 case ecdsa_error::create_context_failed:
return "failed to create context";
194 default:
return "unknown ECDSA error";
198 static ecdsa_error_cat cat;
227 class verification_error_cat :
public std::error_category
230 const char* name()
const noexcept override {
return "signature_verification_error"; };
231 std::string message(
int ev)
const override
235 case signature_verification_error::ok:
return "no error";
236 case signature_verification_error::invalid_signature:
return "invalid signature";
237 case signature_verification_error::create_context_failed:
238 return "failed to verify signature: could not create context";
239 case signature_verification_error::verifyinit_failed:
240 return "failed to verify signature: VerifyInit failed";
241 case signature_verification_error::verifyupdate_failed:
242 return "failed to verify signature: VerifyUpdate failed";
243 case signature_verification_error::verifyfinal_failed:
244 return "failed to verify signature: VerifyFinal failed";
245 case signature_verification_error::get_key_failed:
246 return "failed to verify signature: Could not get key";
247 case signature_verification_error::set_rsa_pss_saltlen_failed:
248 return "failed to verify signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
249 case signature_verification_error::signature_encoding_failed:
250 return "failed to verify signature: i2d_ECDSA_SIG failed";
251 default:
return "unknown signature verification error";
255 static verification_error_cat cat;
290 class signature_generation_error_cat :
public std::error_category
293 const char* name()
const noexcept override {
return "signature_generation_error"; };
294 std::string message(
int ev)
const override
298 case signature_generation_error::ok:
return "no error";
299 case signature_generation_error::hmac_failed:
return "hmac failed";
300 case signature_generation_error::create_context_failed:
301 return "failed to create signature: could not create context";
302 case signature_generation_error::signinit_failed:
303 return "failed to create signature: SignInit failed";
304 case signature_generation_error::signupdate_failed:
305 return "failed to create signature: SignUpdate failed";
306 case signature_generation_error::signfinal_failed:
307 return "failed to create signature: SignFinal failed";
308 case signature_generation_error::ecdsa_do_sign_failed:
309 return "failed to generate ecdsa signature";
310 case signature_generation_error::digestinit_failed:
311 return "failed to create signature: DigestInit failed";
312 case signature_generation_error::digestupdate_failed:
313 return "failed to create signature: DigestUpdate failed";
314 case signature_generation_error::digestfinal_failed:
315 return "failed to create signature: DigestFinal failed";
316 case signature_generation_error::rsa_padding_failed:
317 return "failed to create signature: EVP_PKEY_CTX_set_rsa_padding failed";
318 case signature_generation_error::rsa_private_encrypt_failed:
319 return "failed to create signature: RSA_private_encrypt failed";
320 case signature_generation_error::get_key_failed:
321 return "failed to generate signature: Could not get key";
322 case signature_generation_error::set_rsa_pss_saltlen_failed:
323 return "failed to create signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
324 case signature_generation_error::signature_decoding_failed:
325 return "failed to create signature: d2i_ECDSA_SIG failed";
326 default:
return "unknown signature generation error";
330 static signature_generation_error_cat cat = {};
357 class token_verification_error_cat :
public std::error_category
360 const char* name()
const noexcept override {
return "token_verification_error"; };
361 std::string message(
int ev)
const override
365 case token_verification_error::ok:
return "no error";
366 case token_verification_error::wrong_algorithm:
return "wrong algorithm";
367 case token_verification_error::missing_claim:
368 return "decoded JWT is missing required claim(s)";
369 case token_verification_error::claim_type_missmatch:
370 return "claim type does not match expected type";
371 case token_verification_error::claim_value_missmatch:
372 return "claim value does not match expected value";
373 case token_verification_error::token_expired:
return "token expired";
374 case token_verification_error::audience_missmatch:
375 return "token doesn't contain the required audience";
376 default:
return "unknown token verification error";
380 static token_verification_error_cat cat = {};
409using error::ecdsa_exception;
410using error::rsa_exception;
411using error::signature_generation_exception;
412using error::signature_verification_exception;
413using error::token_verification_exception;
417template <>
struct is_error_code_enum<
jwt::error::rsa_error> : true_type
420template <>
struct is_error_code_enum<
jwt::error::ecdsa_error> : true_type
423template <>
struct is_error_code_enum<
jwt::error::signature_verification_error> : true_type
426template <>
struct is_error_code_enum<
jwt::error::signature_generation_error> : true_type
429template <>
struct is_error_code_enum<
jwt::error::token_verification_error> : true_type
455#if OPENSSL_VERSION_NUMBER <= 0x10100003L
456 std::unique_ptr<BIO,
decltype(&BIO_free_all)> certbio(
457 BIO_new_mem_buf(
const_cast<char*
>(certstr.data()),
static_cast<int>(certstr.size())),
460 std::unique_ptr<BIO,
decltype(&BIO_free_all)> certbio(
461 BIO_new_mem_buf(certstr.data(),
static_cast<int>(certstr.size())), BIO_free_all);
463 std::unique_ptr<BIO,
decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all);
464 if (!certbio || !keybio)
470 std::unique_ptr<X509,
decltype(&X509_free)> cert(
471 PEM_read_bio_X509(certbio.get(),
nullptr,
nullptr,
const_cast<char*
>(pw.c_str())),
478 std::unique_ptr<EVP_PKEY,
decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()),
485 if (PEM_write_bio_PUBKEY(keybio.get(), key.get()) == 0)
491 auto len = BIO_get_mem_data(keybio.get(), &ptr);
492 if (len <= 0 || ptr ==
nullptr)
497 return {ptr,
static_cast<size_t>(len)};
529template <
typename Decode>
534 const auto decodedStr =
decode(cert_base64_der_str);
535 auto c_str =
reinterpret_cast<const unsigned char*
>(decodedStr.c_str());
537 std::unique_ptr<X509,
decltype(&X509_free)> cert(
538 d2i_X509(NULL, &c_str,
static_cast<int>(decodedStr.size())), X509_free);
539 std::unique_ptr<BIO,
decltype(&BIO_free_all)> certbio(BIO_new(BIO_s_mem()), BIO_free_all);
540 if (!cert || !certbio)
546 if (!PEM_write_bio_X509(certbio.get(), cert.get()))
553 const auto len = BIO_get_mem_data(certbio.get(), &ptr);
554 if (len <= 0 || ptr ==
nullptr)
560 return {ptr,
static_cast<size_t>(len)};
577template <
typename Decode>
585#ifndef JWT_DISABLE_BASE64
598 auto decode = [](
const std::string& token)
599 {
return base::decode<alphabet::base64>(base::pad<alphabet::base64>(token)); };
630 const std::string& password,
634 std::unique_ptr<BIO,
decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
640 if (key.substr(0, 27) ==
"-----BEGIN CERTIFICATE-----")
645 const int len =
static_cast<int>(epkey.size());
646 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len)
654 const int len =
static_cast<int>(key.size());
655 if (BIO_write(pubkey_bio.get(), key.data(), len) != len)
662 std::shared_ptr<EVP_PKEY> pkey(
664 pubkey_bio.get(),
nullptr,
nullptr,
665 (
void*)password.data()),
685 const std::string& password =
"")
701 const std::string& password,
704 std::unique_ptr<BIO,
decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
710 const int len =
static_cast<int>(key.size());
711 if (BIO_write(privkey_bio.get(), key.data(), len) != len)
716 std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(privkey_bio.get(),
nullptr,
nullptr,
717 const_cast<char*
>(password.c_str())),
735 const std::string& password =
"")
753 const std::string& password,
757 std::unique_ptr<BIO,
decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
763 if (key.substr(0, 27) ==
"-----BEGIN CERTIFICATE-----")
768 const int len =
static_cast<int>(epkey.size());
769 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len)
777 const int len =
static_cast<int>(key.size());
778 if (BIO_write(pubkey_bio.get(), key.data(), len) != len)
785 std::shared_ptr<EVP_PKEY> pkey(
787 pubkey_bio.get(),
nullptr,
nullptr,
788 (
void*)password.data()),
808 const std::string& password =
"")
824 const std::string& password,
827 std::unique_ptr<BIO,
decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
833 const int len =
static_cast<int>(key.size());
834 if (BIO_write(privkey_bio.get(), key.data(), len) != len)
839 std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(privkey_bio.get(),
nullptr,
nullptr,
840 const_cast<char*
>(password.c_str())),
858 const std::string& password =
"")
872#ifdef JWT_OPENSSL_1_0_0
880 std::string res(BN_num_bytes(bn),
'\0');
882 bn, (
unsigned char*)res.data());
890inline std::unique_ptr<BIGNUM,
decltype(&BN_free)>
raw2bn(
const std::string& raw)
892 return std::unique_ptr<BIGNUM, decltype(&BN_free)>(
893 BN_bin2bn(
reinterpret_cast<const unsigned char*
>(raw.data()),
static_cast<int>(raw.size()),
920 std::string
sign(
const std::string& , std::error_code& ec)
const
932 void verify(
const std::string& ,
const std::string& signature,
933 std::error_code& ec)
const
936 if (!signature.empty())
942 std::string
name()
const {
return "none"; }
956 : secret(
std::move(key)), md(md), alg_name(
std::move(
name))
965 std::string
sign(
const std::string& data, std::error_code& ec)
const
968 std::string res(
static_cast<size_t>(EVP_MAX_MD_SIZE),
'\0');
969 auto len =
static_cast<unsigned int>(res.size());
970 if (HMAC(md(), secret.data(),
static_cast<int>(secret.size()),
971 reinterpret_cast<const unsigned char*
>(data.data()),
static_cast<int>(data.size()),
988 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const
991 auto res =
sign(data, ec);
996 for (
size_t i = 0; i < std::min<size_t>(res.size(), signature.size()); i++)
997 if (res[i] != signature[i])
999 if (res.size() != signature.size())
1011 std::string
name()
const {
return alg_name; }
1015 const std::string secret;
1017 const EVP_MD* (*md)();
1019 const std::string alg_name;
1035 rsa(
const std::string& public_key,
const std::string& private_key,
1036 const std::string& public_key_password,
const std::string& private_key_password,
1037 const EVP_MD* (*md)(), std::string
name)
1038 : md(md), alg_name(
std::move(
name))
1040 if (!private_key.empty())
1044 else if (!public_key.empty())
1057 std::string
sign(
const std::string& data, std::error_code& ec)
const
1060#ifdef JWT_OPENSSL_1_0_0
1061 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1062 EVP_MD_CTX_destroy);
1064 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1072 if (!EVP_SignInit(ctx.get(), md()))
1078 std::string res(EVP_PKEY_size(pkey.get()),
'\0');
1079 unsigned int len = 0;
1081 if (!EVP_SignUpdate(ctx.get(), data.data(), data.size()))
1086 if (EVP_SignFinal(ctx.get(), (
unsigned char*)res.data(), &len, pkey.get()) == 0)
1101 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const
1104#ifdef JWT_OPENSSL_1_0_0
1105 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1106 EVP_MD_CTX_destroy);
1108 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1116 if (!EVP_VerifyInit(ctx.get(), md()))
1121 if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size()))
1127 EVP_VerifyFinal(ctx.get(),
reinterpret_cast<const unsigned char*
>(signature.data()),
1128 static_cast<unsigned int>(signature.size()), pkey.get());
1139 std::string
name()
const {
return alg_name; }
1143 std::shared_ptr<EVP_PKEY> pkey;
1145 const EVP_MD* (*md)();
1147 const std::string alg_name;
1165 ecdsa(
const std::string& public_key,
const std::string& private_key,
1166 const std::string& public_key_password,
const std::string& private_key_password,
1167 const EVP_MD* (*md)(), std::string
name,
size_t siglen)
1168 : md(md), alg_name(
std::move(
name)), signature_length(siglen)
1170 if (!private_key.empty())
1173 check_private_key(pkey.get());
1175 else if (!public_key.empty())
1178 check_public_key(pkey.get());
1187 size_t keysize = EVP_PKEY_bits(pkey.get());
1188 if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
1198 std::string
sign(
const std::string& data, std::error_code& ec)
const
1201#ifdef JWT_OPENSSL_1_0_0
1202 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1203 EVP_MD_CTX_destroy);
1205 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1213 if (!EVP_DigestSignInit(ctx.get(),
nullptr, md(),
nullptr, pkey.get()))
1218 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size()))
1225 if (!EVP_DigestSignFinal(ctx.get(),
nullptr, &len))
1230 std::string res(len,
'\0');
1231 if (!EVP_DigestSignFinal(ctx.get(), (
unsigned char*)res.data(), &len))
1238 return der_to_p1363_signature(res, ec);
1247 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const
1250 std::string der_signature = p1363_to_der_signature(signature, ec);
1256#ifdef JWT_OPENSSL_1_0_0
1257 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1258 EVP_MD_CTX_destroy);
1260 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1268 if (!EVP_DigestVerifyInit(ctx.get(),
nullptr, md(),
nullptr, pkey.get()))
1273 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size()))
1279#if OPENSSL_VERSION_NUMBER < 0x10002000L
1280 unsigned char* der_sig_data =
1281 reinterpret_cast<unsigned char*
>(
const_cast<char*
>(der_signature.data()));
1283 const unsigned char* der_sig_data =
1284 reinterpret_cast<const unsigned char*
>(der_signature.data());
1286 auto res = EVP_DigestVerifyFinal(ctx.get(), der_sig_data,
1287 static_cast<unsigned int>(der_signature.length()));
1303 std::string
name()
const {
return alg_name; }
1306 static void check_public_key(EVP_PKEY* pkey)
1308#ifdef JWT_OPENSSL_3_0
1309 std::unique_ptr<EVP_PKEY_CTX,
decltype(&EVP_PKEY_CTX_free)> ctx(
1310 EVP_PKEY_CTX_new_from_pkey(
nullptr, pkey,
nullptr), EVP_PKEY_CTX_free);
1315 if (EVP_PKEY_public_check(ctx.get()) != 1)
1320 std::unique_ptr<EC_KEY,
decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey),
1326 if (EC_KEY_check_key(eckey.get()) == 0)
1331 static void check_private_key(EVP_PKEY* pkey)
1333#ifdef JWT_OPENSSL_3_0
1334 std::unique_ptr<EVP_PKEY_CTX,
decltype(&EVP_PKEY_CTX_free)> ctx(
1335 EVP_PKEY_CTX_new_from_pkey(
nullptr, pkey,
nullptr), EVP_PKEY_CTX_free);
1340 if (EVP_PKEY_private_check(ctx.get()) != 1)
1345 std::unique_ptr<EC_KEY,
decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey),
1351 if (EC_KEY_check_key(eckey.get()) == 0)
1356 std::string der_to_p1363_signature(
const std::string& der_signature, std::error_code& ec)
const
1358 const unsigned char* possl_signature =
1359 reinterpret_cast<const unsigned char*
>(der_signature.data());
1360 std::unique_ptr<ECDSA_SIG,
decltype(&ECDSA_SIG_free)> sig(
1361 d2i_ECDSA_SIG(
nullptr, &possl_signature, der_signature.length()), ECDSA_SIG_free);
1368#ifdef JWT_OPENSSL_1_0_0
1375 ECDSA_SIG_get0(sig.get(), &r, &s);
1379 if (rr.size() > signature_length / 2 || rs.size() > signature_length / 2)
1380 throw std::logic_error(
"bignum size exceeded expected length");
1381 rr.insert(0, signature_length / 2 - rr.size(),
'\0');
1382 rs.insert(0, signature_length / 2 - rs.size(),
'\0');
1386 std::string p1363_to_der_signature(
const std::string& signature, std::error_code& ec)
const
1389 auto r =
helper::raw2bn(signature.substr(0, signature.size() / 2));
1393#ifdef JWT_OPENSSL_1_0_0
1399 std::unique_ptr<ECDSA_SIG,
decltype(&ECDSA_SIG_free)> sig(ECDSA_SIG_new(), ECDSA_SIG_free);
1405 ECDSA_SIG_set0(sig.get(), r.release(), s.release());
1409 int length = i2d_ECDSA_SIG(psig,
nullptr);
1415 std::string der_signature(length,
'\0');
1416 unsigned char* psbuffer = (
unsigned char*)der_signature.data();
1417 length = i2d_ECDSA_SIG(psig, &psbuffer);
1423 der_signature.resize(length);
1424 return der_signature;
1428 std::shared_ptr<EVP_PKEY> pkey;
1430 const EVP_MD* (*md)();
1432 const std::string alg_name;
1434 const size_t signature_length;
1437#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1458 eddsa(
const std::string& public_key,
const std::string& private_key,
1459 const std::string& public_key_password,
const std::string& private_key_password,
1463 if (!private_key.empty())
1467 else if (!public_key.empty())
1480 std::string
sign(
const std::string& data, std::error_code& ec)
const
1483#ifdef JWT_OPENSSL_1_0_0
1484 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1485 &EVP_MD_CTX_destroy);
1487 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(),
1495 if (!EVP_DigestSignInit(ctx.get(),
nullptr,
nullptr,
nullptr, pkey.get()))
1501 size_t len = EVP_PKEY_size(pkey.get());
1502 std::string res(len,
'\0');
1507#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1509 if (EVP_DigestSignUpdate(ctx.get(),
reinterpret_cast<const unsigned char*
>(data.data()),
1512 std::cout << ERR_error_string(ERR_get_error(), NULL) << std::endl;
1516 if (EVP_DigestSignFinal(ctx.get(),
reinterpret_cast<unsigned char*
>(&res[0]), &len) != 1)
1522 if (EVP_DigestSign(ctx.get(),
reinterpret_cast<unsigned char*
>(&res[0]), &len,
1523 reinterpret_cast<const unsigned char*
>(data.data()), data.size()) != 1)
1540 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const
1543#ifdef JWT_OPENSSL_1_0_0
1544 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1545 &EVP_MD_CTX_destroy);
1547 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(),
1555 if (!EVP_DigestVerifyInit(ctx.get(),
nullptr,
nullptr,
nullptr, pkey.get()))
1563#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1564 if (EVP_DigestVerifyUpdate(ctx.get(),
reinterpret_cast<const unsigned char*
>(data.data()),
1570 if (EVP_DigestVerifyFinal(ctx.get(),
1571 reinterpret_cast<const unsigned char*
>(signature.data()),
1572 signature.size()) != 1)
1578 auto res = EVP_DigestVerify(
1579 ctx.get(),
reinterpret_cast<const unsigned char*
>(signature.data()), signature.size(),
1580 reinterpret_cast<const unsigned char*
>(data.data()), data.size());
1592 std::string
name()
const {
return alg_name; }
1596 std::shared_ptr<EVP_PKEY> pkey;
1598 const std::string alg_name;
1615 pss(
const std::string& public_key,
const std::string& private_key,
1616 const std::string& public_key_password,
const std::string& private_key_password,
1617 const EVP_MD* (*md)(), std::string
name)
1618 : md(md), alg_name(
std::move(
name))
1620 if (!private_key.empty())
1624 else if (!public_key.empty())
1638 std::string
sign(
const std::string& data, std::error_code& ec)
const
1641#ifdef JWT_OPENSSL_1_0_0
1642 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> md_ctx(EVP_MD_CTX_create(),
1643 &EVP_MD_CTX_destroy);
1645 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(),
1653 EVP_PKEY_CTX* ctx =
nullptr;
1654 if (EVP_DigestSignInit(md_ctx.get(), &ctx, md(),
nullptr, pkey.get()) != 1)
1659 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
1666#ifndef LIBWOLFSSL_VERSION_HEX
1667 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
1673 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1)
1679 size_t size = EVP_PKEY_size(pkey.get());
1680 std::string res(size, 0x00);
1681 if (EVP_DigestSignFinal(
1700 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const
1704#ifdef JWT_OPENSSL_1_0_0
1705 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_destroy)> md_ctx(EVP_MD_CTX_create(),
1706 &EVP_MD_CTX_destroy);
1708 std::unique_ptr<EVP_MD_CTX,
decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(),
1716 EVP_PKEY_CTX* ctx =
nullptr;
1717 if (EVP_DigestVerifyInit(md_ctx.get(), &ctx, md(),
nullptr, pkey.get()) != 1)
1722 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
1729#ifndef LIBWOLFSSL_VERSION_HEX
1730 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
1736 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1)
1742 if (EVP_DigestVerifyFinal(md_ctx.get(), (
unsigned char*)signature.data(),
1743 signature.size()) <= 0)
1753 std::string
name()
const {
return alg_name; }
1757 std::shared_ptr<EVP_PKEY> pkey;
1759 const EVP_MD* (*md)();
1761 const std::string alg_name;
1809 explicit rs256(
const std::string& public_key,
const std::string& private_key =
"",
1810 const std::string& public_key_password =
"",
1811 const std::string& private_key_password =
"")
1812 :
rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
1829 explicit rs384(
const std::string& public_key,
const std::string& private_key =
"",
1830 const std::string& public_key_password =
"",
1831 const std::string& private_key_password =
"")
1832 :
rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
1849 explicit rs512(
const std::string& public_key,
const std::string& private_key =
"",
1850 const std::string& public_key_password =
"",
1851 const std::string& private_key_password =
"")
1852 :
rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
1871 explicit es256(
const std::string& public_key,
const std::string& private_key =
"",
1872 const std::string& public_key_password =
"",
1873 const std::string& private_key_password =
"")
1874 :
ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
1893 explicit es384(
const std::string& public_key,
const std::string& private_key =
"",
1894 const std::string& public_key_password =
"",
1895 const std::string& private_key_password =
"")
1896 :
ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
1915 explicit es512(
const std::string& public_key,
const std::string& private_key =
"",
1916 const std::string& public_key_password =
"",
1917 const std::string& private_key_password =
"")
1918 :
ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
1936 explicit es256k(
const std::string& public_key,
const std::string& private_key =
"",
1937 const std::string& public_key_password =
"",
1938 const std::string& private_key_password =
"")
1939 :
ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
1945#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1964 explicit ed25519(
const std::string& public_key,
const std::string& private_key =
"",
1965 const std::string& public_key_password =
"",
1966 const std::string& private_key_password =
"")
1967 :
eddsa(public_key, private_key, public_key_password, private_key_password,
"EdDSA")
1990 explicit ed448(
const std::string& public_key,
const std::string& private_key =
"",
1991 const std::string& public_key_password =
"",
1992 const std::string& private_key_password =
"")
1993 :
eddsa(public_key, private_key, public_key_password, private_key_password,
"EdDSA")
2011 explicit ps256(
const std::string& public_key,
const std::string& private_key =
"",
2012 const std::string& public_key_password =
"",
2013 const std::string& private_key_password =
"")
2014 :
pss(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
2031 explicit ps384(
const std::string& public_key,
const std::string& private_key =
"",
2032 const std::string& public_key_password =
"",
2033 const std::string& private_key_password =
"")
2034 :
pss(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
2051 explicit ps512(
const std::string& public_key,
const std::string& private_key =
"",
2052 const std::string& public_key_password =
"",
2053 const std::string& private_key_password =
"")
2054 :
pss(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
2084#ifdef __cpp_lib_void_t
2085template <
typename... Ts>
using void_t = std::void_t<Ts...>;
2096#ifdef __cpp_lib_experimental_detect
2097template <
template <
typename...>
class _Op,
typename... _Args>
2098using is_detected = std::experimental::is_detected<_Op, _Args...>;
2100template <
template <
typename...>
class _Op,
typename... _Args>
2101using is_detected_t = std::experimental::detected_t<_Op, _Args...>;
2114template <
class Default,
class AlwaysVoid,
template <
class...>
class Op,
class... Args>
2121template <
class Default,
template <
class...>
class Op,
class... Args>
2128template <
template <
class...>
class Op,
class... Args>
2131template <
template <
class...>
class Op,
class... Args>
2137template <
typename traits_type,
typename value_type>
2139 typename std::is_same<get_type_function<traits_type>, json::type(
const value_type&)>;
2144 std::is_function<get_type_function<traits_type>>
::value &&
2150template <
typename traits_type,
typename value_type,
typename object_type>
2152 typename std::is_same<as_object_function<traits_type>, object_type(
const value_type&)>;
2157 std::is_constructible<value_type, object_type>::value &&
2159 std::is_function<as_object_function<traits_type>>
::value &&
2165template <
typename traits_type,
typename value_type,
typename array_type>
2167 typename std::is_same<as_array_function<traits_type>, array_type(
const value_type&)>;
2171 static constexpr auto value = std::is_constructible<value_type, array_type>::value &&
2173 std::is_function<as_array_function<traits_type>>
::value &&
2179template <
typename traits_type,
typename value_type,
typename string_type>
2181 typename std::is_same<as_string_function<traits_type>, string_type(
const value_type&)>;
2186 std::is_constructible<value_type, string_type>::value &&
2188 std::is_function<as_string_function<traits_type>>
::value &&
2194template <
typename traits_type,
typename value_type,
typename number_type>
2196 typename std::is_same<as_number_function<traits_type>, number_type(
const value_type&)>;
2201 std::is_floating_point<number_type>::value &&
2202 std::is_constructible<value_type, number_type>::value &&
2204 std::is_function<as_number_function<traits_type>>
::value &&
2210template <
typename traits_type,
typename value_type,
typename integer_type>
2212 typename std::is_same<as_integer_function<traits_type>, integer_type(
const value_type&)>;
2214template <
typename traits_type,
typename value_type,
typename integer_type>
2218 std::is_signed<integer_type>::value && !std::is_floating_point<integer_type>::value &&
2219 std::is_constructible<value_type, integer_type>::value &&
2221 std::is_function<as_integer_function<traits_type>>
::value &&
2227template <
typename traits_type,
typename value_type,
typename boolean_type>
2229 typename std::is_same<as_boolean_function<traits_type>, boolean_type(
const value_type&)>;
2231template <
typename traits_type,
typename value_type,
typename boolean_type>
2235 std::is_convertible<boolean_type, bool>::value &&
2236 std::is_constructible<value_type, boolean_type>::value &&
2238 std::is_function<as_boolean_function<traits_type>>
::value &&
2246 "traits must provide `jwt::json::type get_type(const value_type&)`");
2248 typename traits::object_type>
::value,
2249 "traits must provide `object_type as_object(const value_type&)`");
2252 "traits must provide `array_type as_array(const value_type&)`");
2254 typename traits::string_type>
::value,
2255 "traits must provide `string_type as_string(const value_type&)`");
2257 typename traits::number_type>
::value,
2258 "traits must provide `number_type as_number(const value_type&)`");
2260 typename traits::integer_type>
::value,
2261 "traits must provide `integer_type as_int(const value_type&)`");
2263 typename traits::boolean_type>
::value,
2264 "traits must provide `boolean_type as_bool(const value_type&)`");
2268 typename traits::object_type>
::value &&
2270 typename traits::array_type>
::value &&
2272 typename traits::string_type>
::value &&
2274 typename traits::number_type>
::value &&
2276 typename traits::integer_type>
::value &&
2278 typename traits::boolean_type>
::value;
2284 std::is_default_constructible<value_type>::value &&
2285 std::is_constructible<value_type,
2287 std::is_move_constructible<value_type>::value &&
2288 std::is_assignable<value_type, value_type>::value &&
2289 std::is_copy_assignable<value_type>::value && std::is_move_assignable<value_type>::value;
2295template <
typename traits_type>
using has_key_type =
typename traits_type::key_type;
2297template <
typename traits_type>
using has_value_type =
typename traits_type::value_type;
2299template <
typename object_type>
using has_iterator =
typename object_type::iterator;
2303template <
typename object_type>
2307template <
typename object_type>
2309 typename std::is_same<decltype(std::declval<const object_type>().begin()),
2320template <
typename object_type>
2324template <
typename object_type>
2326 typename std::is_same<decltype(std::declval<const object_type>().end()),
2337template <
typename object_type,
typename string_type>
2339 typename std::is_integral<decltype(std::declval<const object_type>().count(
2340 std::declval<const string_type>()))>;
2348 template <
class T,
class A0>
2353 static constexpr auto value =
decltype(test_operator_plus<object_type, string_type>(0)){};
2356template <
typename object_type,
typename value_type,
typename string_type>
2362 "object_type must implementate the subscription operator '[]' for this library");
2367template <
typename object_type,
typename value_type,
typename string_type>
2369 std::declval<const string_type>())),
2372template <
typename value_type,
typename string_type,
typename object_type>
2377 std::is_same<typename object_type::mapped_type, value_type>::value &&
2379 (std::is_same<typename object_type::key_type, string_type>::value ||
2380 std::is_constructible<typename object_type::key_type, string_type>::value) &&
2388 std::is_same<
typename object_type::value_type,
2389 std::pair<const string_type, value_type>>
::value;
2394 static constexpr auto value = std::is_same<typename array_type::value_type, value_type>::value;
2397template <
typename string_type,
typename integer_type>
2399 typename std::is_same<decltype(std::declval<string_type>().substr(
2400 std::declval<integer_type>(), std::declval<integer_type>())),
2403template <
typename string_type,
typename integer_type>
2405 decltype(std::declval<string_type>().substr(std::declval<integer_type>())), string_type>;
2413 template <
class T,
class A0>
2418 static constexpr auto value =
decltype(test_operator_plus<string_type, string_type>(0)){};
2421template <
typename string_type>
2423 typename std::is_same<decltype(std::operator+(std::declval<string_type>(),
2424 std::declval<string_type>())),
2433 "string_type must have a substr method taking only a start index and an overload "
2434 "taking a start and end index, both must return a string_type");
2440 "string_type must have a '+' operator implemented which returns the concatenated string");
2445template <
typename value_type,
typename string_type,
typename integer_type,
typename object_type,
2446 typename array_type>
2452 "value_type must meet basic requirements, default constructor, copyable, moveable");
2454 "object_type must be a string_type to value_type container");
2456 "array_type must be a container of value_type");
2481 static_assert(std::is_same<typename json_traits::string_type, std::string>::value ||
2482 std::is_convertible<typename json_traits::string_type, std::string>::value ||
2483 std::is_constructible<typename json_traits::string_type, std::string>::value,
2484 "string_type must be a std::string, convertible to a std::string, or construct a "
2488 typename json_traits::value_type,
typename json_traits::string_type,
2489 typename json_traits::integer_type,
typename json_traits::object_type,
2490 typename json_traits::array_type>::value,
2491 "must staisfy json container requirements");
2494 typename json_traits::value_type val;
2497 using set_t = std::set<typename json_traits::string_type>;
2508 : val(typename json_traits::integer_type(
std::chrono::system_clock::to_time_t(d)))
2514 : val(typename json_traits::array_type(s.begin(), s.end()))
2517 template <
typename Iterator>
2518 basic_claim(Iterator begin, Iterator end) : val(typename json_traits::array_type(begin, end))
2526 typename json_traits::value_type
to_json()
const {
return val; }
2545 json::type
get_type()
const {
return json_traits::get_type(val); }
2552 typename json_traits::string_type
as_string()
const {
return json_traits::as_string(val); }
2566 typename json_traits::array_type
as_array()
const {
return json_traits::as_array(val); }
2576 for (
const auto& e : json_traits::as_array(val)) { res.insert(json_traits::as_string(e)); }
2585 typename json_traits::integer_type
as_int()
const {
return json_traits::as_int(val); }
2592 typename json_traits::boolean_type
as_bool()
const {
return json_traits::as_bool(val); }
2599 typename json_traits::number_type
as_number()
const {
return json_traits::as_number(val); }
2624 typename json_traits::object_type claims;
2628 using iterator =
typename json_traits::object_type::iterator;
2654 static typename json_traits::object_type
2657 typename json_traits::value_type val;
2658 if (!json_traits::parse(val, str))
2661 return json_traits::as_object(val);
2668 bool has_claim(
const typename json_traits::string_type& name)
const noexcept
2670 return claims.count(name) != 0;
2687 std::unordered_map<typename json_traits::string_type, basic_claim_t>
get_claims()
const
2690 typename json_traits::value_type,
typename json_traits::string_type,
2691 typename json_traits::object_type>::supports_claims_transform,
2692 "currently there is a limitation on the internal implemantation of the "
2693 "`object_type` to have an "
2694 "`std::pair` like `value_type`");
2696 std::unordered_map<typename json_traits::string_type, basic_claim_t> res;
2697 std::transform(claims.begin(), claims.end(), std::inserter(res, res.end()),
2698 [](
const typename json_traits::object_type::value_type& val)
2699 { return std::make_pair(val.first, basic_claim_t{val.second}); });
2721 bool has_issuer() const noexcept {
return has_payload_claim(
"iss"); }
2726 bool has_subject() const noexcept {
return has_payload_claim(
"sub"); }
2751 bool has_id() const noexcept {
return has_payload_claim(
"jti"); }
2760 return get_payload_claim(
"iss").as_string();
2770 return get_payload_claim(
"sub").as_string();
2780 auto aud = get_payload_claim(
"aud");
2781 if (aud.get_type() == json::type::string)
2782 return {aud.as_string()};
2784 return aud.as_set();
2813 typename json_traits::string_type
get_id()
const
2815 return get_payload_claim(
"jti").as_string();
2856 bool has_type() const noexcept {
return has_header_claim(
"typ"); }
2866 bool has_key_id() const noexcept {
return has_header_claim(
"kid"); }
2875 return get_header_claim(
"alg").as_string();
2885 return get_header_claim(
"typ").as_string();
2895 return get_header_claim(
"cty").as_string();
2905 return get_header_claim(
"kid").as_string();
2929template <
typename json_traits>
2934 const typename json_traits::string_type
token;
2950#ifndef JWT_DISABLE_BASE64
2962 token, [](const typename json_traits::string_type& str)
2963 {
return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(str)); })
2978 template <
typename Decode>
2979 decoded_jwt(
const typename json_traits::string_type& token, Decode decode) : token(token)
2981 auto hdr_end = token.find(
'.');
2982 if (hdr_end == json_traits::string_type::npos)
2983 throw std::invalid_argument(
"invalid token supplied");
2984 auto payload_end = token.find(
'.', hdr_end + 1);
2985 if (payload_end == json_traits::string_type::npos)
2986 throw std::invalid_argument(
"invalid token supplied");
2987 header_base64 = token.substr(0, hdr_end);
2988 payload_base64 = token.substr(hdr_end + 1, payload_end - hdr_end - 1);
2989 signature_base64 = token.substr(payload_end + 1);
2993 signature =
decode(signature_base64);
3003 const typename json_traits::string_type&
get_token() const noexcept {
return token; }
3018 const typename json_traits::string_type&
get_signature() const noexcept {
return signature; }
3025 return header_base64;
3033 return payload_base64;
3041 return signature_base64;
3049 return this->payload_claims.get_claims();
3057 return this->header_claims.get_claims();
3068 return this->payload_claims.get_claim(name);
3079 return this->header_claims.get_claim(name);
3089 typename json_traits::object_type header_claims;
3090 typename json_traits::object_type payload_claims;
3101 typename json_traits::value_type c)
3103 header_claims[id] = std::move(c);
3116 header_claims[id] = c.
to_json();
3126 typename json_traits::value_type c)
3128 payload_claims[id] = std::move(c);
3140 payload_claims[id] = c.
to_json();
3152 return set_header_claim(
"alg",
typename json_traits::value_type(str));
3161 return set_header_claim(
"typ",
typename json_traits::value_type(str));
3170 return set_header_claim(
"cty",
typename json_traits::value_type(str));
3180 return set_header_claim(
"kid",
typename json_traits::value_type(str));
3189 return set_payload_claim(
"iss",
typename json_traits::value_type(str));
3198 return set_payload_claim(
"sub",
typename json_traits::value_type(str));
3207 return set_payload_claim(
"aud",
typename json_traits::value_type(a));
3216 return set_payload_claim(
"aud",
typename json_traits::value_type(aud));
3252 return set_payload_claim(
"jti",
typename json_traits::value_type(str));
3266 template <
typename Algo,
typename Encode>
3267 typename json_traits::string_type
sign(
const Algo& algo, Encode encode)
const
3270 auto res = sign(algo, encode, ec);
3271 error::throw_if_error(ec);
3274#ifndef JWT_DISABLE_BASE64
3283 template <
typename Algo>
typename json_traits::string_type
sign(
const Algo& algo)
const
3286 auto res = sign(algo, ec);
3287 error::throw_if_error(ec);
3304 template <
typename Algo,
typename Encode>
3305 typename json_traits::string_type
sign(
const Algo& algo, Encode encode,
3306 std::error_code& ec)
const
3309 typename json_traits::object_type obj_header = header_claims;
3310 if (header_claims.count(
"alg") == 0)
3311 obj_header[
"alg"] =
typename json_traits::value_type(algo.name());
3314 encode(json_traits::serialize(
typename json_traits::value_type(obj_header)));
3316 encode(json_traits::serialize(
typename json_traits::value_type(payload_claims)));
3319 auto signature = algo.sign(token, ec);
3323 return token +
"." + encode(signature);
3325#ifndef JWT_DISABLE_BASE64
3335 template <
typename Algo>
3336 typename json_traits::string_type
sign(
const Algo& algo, std::error_code& ec)
const
3340 [](
const typename json_traits::string_type& data)
3341 {
return base::trim<alphabet::base64url>(base::encode<alphabet::base64url>(data)); },
3355 : current_time(ctime),
jwt(j), default_leeway(l)
3363 size_t default_leeway{0};
3366 typename json_traits::string_type claim_key{};
3373 if (!
jwt.has_header_claim(claim_key))
3375 ec = error::token_verification_error::missing_claim;
3378 return jwt.get_header_claim(claim_key);
3382 if (!
jwt.has_payload_claim(claim_key))
3384 ec = error::token_verification_error::missing_claim;
3387 return jwt.get_payload_claim(claim_key);
3392 auto c = get_claim(in_header, ec);
3395 if (c.get_type() != t)
3397 ec = error::token_verification_error::claim_type_missmatch;
3405 return get_claim(
false, t, ec);
3420 const bool matches = [&]()
3424 case json::type::boolean:
return expected.
as_bool() == jc.as_bool();
3425 case json::type::integer:
return expected.
as_int() == jc.as_int();
3426 case json::type::number:
return expected.
as_number() == jc.as_number();
3427 case json::type::string:
return expected.
as_string() == jc.as_string();
3428 case json::type::array:
3429 case json::type::object:
3430 return json_traits::serialize(expected.
to_json()) ==
3431 json_traits::serialize(jc.to_json());
3432 default:
throw std::logic_error(
"internal error, should be unreachable");
3437 ec = error::token_verification_error::claim_value_missmatch;
3452 auto jc = ctx.
get_claim(in_header, json::type::integer, ec);
3455 auto c = jc.as_date();
3456 if (ctx.
current_time > c + std::chrono::seconds(leeway))
3458 ec = error::token_verification_error::token_expired;
3472 auto jc = ctx.
get_claim(in_header, json::type::integer, ec);
3475 auto c = jc.as_date();
3476 if (ctx.
current_time < c - std::chrono::seconds(leeway))
3478 ec = error::token_verification_error::token_expired;
3496 if (c.get_type() == json::type::string)
3498 if (expected.size() != 1 || *expected.begin() != c.
as_string())
3500 ec = error::token_verification_error::audience_missmatch;
3504 else if (c.get_type() == json::type::array)
3506 auto jc = c.as_set();
3507 for (
auto& e : expected)
3509 if (jc.find(e) == jc.end())
3511 ec = error::token_verification_error::audience_missmatch;
3518 ec = error::token_verification_error::claim_type_missmatch;
3532 : expected(to_lower_unicode(e, loc)), locale(loc)
3538 const auto c = ctx.
get_claim(in_header, json::type::string, ec);
3541 if (to_lower_unicode(c.as_string(), locale) != expected)
3543 ec = error::token_verification_error::claim_value_missmatch;
3549 std::wstring_convert<std::codecvt_utf8<wchar_t>,
wchar_t> conv;
3550 auto wide = conv.from_bytes(str);
3551 auto& f = std::use_facet<std::ctype<wchar_t>>(loc);
3552 f.tolower(&wide[0], &wide[0] + wide.size());
3553 return conv.to_bytes(wide);
3562template <
typename Clock,
typename json_traits>
class verifier
3581 virtual ~algo_base() =
default;
3582 virtual void verify(
const std::string& data,
const std::string& sig,
3583 std::error_code& ec) = 0;
3585 template <
typename T>
struct algo :
public algo_base
3588 explicit algo(T a) : alg(a) {}
3589 void verify(
const std::string& data,
const std::string& sig, std::error_code& ec)
override
3591 alg.verify(data, sig, ec);
3595 std::unordered_map<typename json_traits::string_type, verify_check_fn_t> claims;
3597 size_t default_leeway = 0;
3601 std::unordered_map<std::string, std::shared_ptr<algo_base>> algs;
3612 if (!ctx.
jwt.has_expires_at())
3614 auto exp = ctx.
jwt.get_expires_at();
3617 ec = error::token_verification_error::token_expired;
3622 if (!ctx.
jwt.has_issued_at())
3624 auto iat = ctx.
jwt.get_issued_at();
3627 ec = error::token_verification_error::token_expired;
3632 if (!ctx.
jwt.has_not_before())
3634 auto nbf = ctx.
jwt.get_not_before();
3637 ec = error::token_verification_error::token_expired;
3649 default_leeway = leeway;
3698 std::locale locale = std::locale{})
3701 type, std::move(locale)});
3746 return with_audience(s);
3789 algs[alg.name()] = std::make_shared<algo<Algorithm>>(alg);
3802 error::throw_if_error(ec);
3812 const typename json_traits::string_type data =
3813 jwt.get_header_base64() +
"." +
jwt.get_payload_base64();
3814 const typename json_traits::string_type sig =
jwt.get_signature();
3815 const std::string algo =
jwt.get_algorithm();
3816 if (algs.count(algo) == 0)
3818 ec = error::token_verification_error::wrong_algorithm;
3821 algs.at(algo)->verify(data, sig, ec);
3826 for (
auto& c : claims)
3828 ctx.claim_key = c.first;
3844template <
typename json_traits>
class jwk
3851 : jwk_claims(details::map_of_claims<json_traits>::parse_claims(str))
3856 : jwk_claims(json_traits::as_object(
json))
3870 return get_jwk_claim(
"kty").as_string();
3879 typename json_traits::string_type
get_use()
const {
return get_jwk_claim(
"use").as_string(); }
3889 return get_jwk_claim(
"key_ops").as_set();
3900 return get_jwk_claim(
"alg").as_string();
3911 return get_jwk_claim(
"kid").as_string();
3924 typename json_traits::string_type
get_curve()
const {
return get_jwk_claim(
"crv").as_string(); }
3932 typename json_traits::array_type
get_x5c()
const {
return get_jwk_claim(
"x5c").as_array(); };
3940 typename json_traits::string_type
get_x5u()
const {
return get_jwk_claim(
"x5u").as_string(); };
3948 typename json_traits::string_type
get_x5t()
const {
return get_jwk_claim(
"x5t").as_string(); };
3958 return get_jwk_claim(
"x5t#S256").as_string();
3969 auto x5c_array = get_jwk_claim(
"x5c").as_array();
3970 if (x5c_array.size() == 0)
3973 return json_traits::as_string(x5c_array.front());
3986 bool has_use() const noexcept {
return has_jwk_claim(
"use"); }
4004 bool has_curve() const noexcept {
return has_jwk_claim(
"crv"); }
4010 bool has_key_id() const noexcept {
return has_jwk_claim(
"kid"); }
4016 bool has_x5u() const noexcept {
return has_jwk_claim(
"x5u"); }
4022 bool has_x5c() const noexcept {
return has_jwk_claim(
"x5c"); }
4028 bool has_x5t() const noexcept {
return has_jwk_claim(
"x5t"); }
4040 bool has_jwk_claim(
const typename json_traits::string_type& name)
const noexcept
4055 bool empty() const noexcept {
return jwk_claims.empty(); }
4068template <
typename json_traits>
class jwks
4078 typename json_traits::value_type parsed_val;
4079 if (!json_traits::parse(parsed_val, str))
4087 std::transform(jwk_list.begin(), jwk_list.end(), std::back_inserter(jwk_claims),
4088 [](
const typename json_traits::value_type& val) { return jwk_t{val}; });
4102 bool has_jwk(
const typename json_traits::string_type& key_id)
const noexcept
4104 return find_by_kid(key_id) != end();
4114 const auto maybe = find_by_kid(key_id);
4121 jwt_vector_t jwk_claims;
4123 const_iterator find_by_kid(
const typename json_traits::string_type& key_id)
const noexcept
4125 return std::find_if(cbegin(), cend(),
4126 [key_id](
const jwk_t&
jwk)
4162 return verifier<default_clock, json_traits>(c);
4178template <
typename json_traits,
typename Decode>
4191template <
typename json_traits>
4197template <
typename json_traits>
4203template <
typename json_traits>
4210template <
typename json_traits>
4213 return c.operator>>(is);
4216template <
typename json_traits>
4222#ifndef JWT_DISABLE_PICOJSON
4223#include "traits/kazuho-picojson/defaults.h"
a class to store a generic JSON value as claim
basic_claim & operator=(basic_claim &&)=default
basic_claim(basic_claim &&)=default
json_traits::number_type as_number() const
json_traits::integer_type as_int() const
basic_claim & operator=(const basic_claim &)=default
basic_claim(const basic_claim &)=default
json::type get_type() const
json_traits::boolean_type as_bool() const
basic_claim(Iterator begin, Iterator end)
std::set< typename json_traits::string_type > set_t
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s)
std::istream & operator>>(std::istream &is)
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a)
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v)
std::ostream & operator<<(std::ostream &os)
JWT_CLAIM_EXPLICIT basic_claim(const set_t &s)
json_traits::value_type to_json() const
json_traits::array_type as_array() const
JWT_CLAIM_EXPLICIT basic_claim(const date &d)
json_traits::string_type as_string() const
builder & set_payload_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
json_traits::string_type sign(const Algo &algo) const
json_traits::string_type sign(const Algo &algo, Encode encode) const
builder & set_audience(typename json_traits::string_type aud)
builder & set_audience(typename json_traits::array_type a)
builder & set_header_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
builder & set_payload_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
builder & set_subject(typename json_traits::string_type str)
builder & set_content_type(typename json_traits::string_type str)
builder & set_not_before(const date &d)
builder & set_issued_at(const date &d)
builder & set_id(const typename json_traits::string_type &str)
builder & set_type(typename json_traits::string_type str)
builder & set_key_id(typename json_traits::string_type str)
Set key id claim.
builder & set_issuer(typename json_traits::string_type str)
builder & set_header_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
builder & set_algorithm(typename json_traits::string_type str)
Set algorithm claim You normally don't need to do this, as the algorithm is automatically set if you ...
json_traits::string_type sign(const Algo &algo, std::error_code &ec) const
builder & set_expires_at(const date &d)
json_traits::string_type sign(const Algo &algo, Encode encode, std::error_code &ec) const
const json_traits::string_type & get_header() const noexcept
const json_traits::string_type & get_signature_base64() const noexcept
json_traits::string_type signature
Signature part decoded from base64.
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_header_claims() const
json_traits::string_type header
Header part decoded from base64.
json_traits::string_type header_base64
Unmodified header part in base64.
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
const json_traits::string_type & get_signature() const noexcept
JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type &token)
Parses a given token.
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_payload_claims() const
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
decoded_jwt(const typename json_traits::string_type &token, Decode decode)
Parses a given token.
json_traits::string_type signature_base64
Unmodified signature part in base64.
const json_traits::string_type token
Unmodifed token, as passed to constructor.
const json_traits::string_type & get_payload_base64() const noexcept
const json_traits::string_type & get_token() const noexcept
const json_traits::string_type & get_payload() const noexcept
const json_traits::string_type & get_header_base64() const noexcept
json_traits::string_type payload_base64
Unmodified payload part in base64.
json_traits::string_type payload
Payload part decoded from base64.
map_of_claims & operator=(const map_of_claims &)=default
basic_claim_t get_claim(const typename json_traits::string_type &name) const
bool has_claim(const typename json_traits::string_type &name) const noexcept
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_claims() const
typename json_traits::object_type::const_iterator const_iterator
const_iterator cbegin() const
const_iterator begin() const
static json_traits::object_type parse_claims(const typename json_traits::string_type &str)
Parse a JSON string into a map of claims.
typename json_traits::object_type::iterator iterator
map_of_claims & operator=(map_of_claims &&)=default
map_of_claims(typename json_traits::object_type json)
map_of_claims(map_of_claims &&)=default
const_iterator cend() const
const_iterator end() const
map_of_claims(const map_of_claims &)=default
bool has_x5c() const noexcept
json_traits::string_type get_curve() const
Get curve claim.
bool has_x5t_sha256() const noexcept
JWT_CLAIM_EXPLICIT jwk(const typename json_traits::string_type &str)
json_traits::string_type get_algorithm() const
json_traits::array_type get_x5c() const
json_traits::string_type get_x5t() const
json_traits::string_type get_x5c_key_value() const
json_traits::string_type get_x5t_sha256() const
json_traits::string_type get_key_id() const
bool has_algorithm() const noexcept
json_traits::string_type get_use() const
bool has_key_id() const noexcept
bool has_x5u() const noexcept
bool has_key_operations() const noexcept
bool empty() const noexcept
bool has_use() const noexcept
bool has_x5t() const noexcept
bool has_jwk_claim(const typename json_traits::string_type &name) const noexcept
basic_claim_t::set_t get_key_operations() const
bool has_curve() const noexcept
bool has_key_type() const noexcept
basic_claim_t get_jwk_claim(const typename json_traits::string_type &name) const
json_traits::string_type get_x5u() const
JWT_CLAIM_EXPLICIT jwk(const typename json_traits::value_type &json)
json_traits::string_type get_key_type() const
const_iterator cend() const
const_iterator cbegin() const
typename jwt_vector_t::const_iterator const_iterator
std::vector< jwk_t > jwt_vector_t
const_iterator end() const
const_iterator begin() const
jwk_t get_jwk(const typename json_traits::string_type &key_id) const
typename jwt_vector_t::iterator iterator
JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type &str)
bool has_jwk(const typename json_traits::string_type &key_id) const noexcept
basic_claim_t::set_t get_audience() const
json_traits::string_type get_id() const
bool has_issued_at() const noexcept
bool has_not_before() const noexcept
bool has_payload_claim(const typename json_traits::string_type &name) const noexcept
bool has_subject() const noexcept
details::map_of_claims< json_traits > payload_claims
date get_not_before() const
bool has_issuer() const noexcept
bool has_id() const noexcept
bool has_expires_at() const noexcept
date get_issued_at() const
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
bool has_audience() const noexcept
date get_expires_at() const
json_traits::string_type get_subject() const
json_traits::string_type get_issuer() const
verifier & expires_at_leeway(size_t leeway)
std::function< void(const verify_ops::verify_context< json_traits > &, std::error_code &ec)> verify_check_fn_t
verifier & with_claim(const typename json_traits::string_type &name, verify_check_fn_t fn)
void verify(const decoded_jwt< json_traits > &jwt, std::error_code &ec) const
verifier & not_before_leeway(size_t leeway)
verifier & issued_at_leeway(size_t leeway)
verifier & with_subject(const typename json_traits::string_type &sub)
verifier & with_audience(const typename basic_claim_t::set_t &aud)
verifier & with_claim(const typename json_traits::string_type &name, basic_claim_t c)
verifier & with_audience(const typename json_traits::string_type &aud)
void verify(const decoded_jwt< json_traits > &jwt) const
verifier & leeway(size_t leeway)
verifier & with_issuer(const typename json_traits::string_type &iss)
verifier & allow_algorithm(Algorithm alg)
verifier & with_type(const typename json_traits::string_type &type, std::locale locale=std::locale{})
verifier & with_id(const typename json_traits::string_type &id)
#define JWT_CLAIM_EXPLICIT
std::istream & operator>>(std::istream &is, jwt::basic_claim< json_traits > &c)
decltype(traits_type::as_bool) as_boolean_function
typename std::is_same< decltype(std::operator+(std::declval< string_type >(), std::declval< string_type >())), string_type > is_std_operate_plus_signature
decltype(traits_type::as_int) as_integer_function
typename detector< nonesuch, void, Op, Args... >::type is_detected_t
typename std::is_same< decltype(std::declval< object_type >().begin()), has_iterator< object_type > > is_begin_signature
typename make_void< Ts... >::type void_t
decltype(traits_type::as_array) as_array_function
typename std::is_same< as_boolean_function< traits_type >, boolean_type(const value_type &)> is_as_boolean_signature
decltype(traits_type::as_string) as_string_function
typename std::is_same< as_object_function< traits_type >, object_type(const value_type &)> is_as_object_signature
typename std::is_same< decltype(std::declval< const object_type >().at(std::declval< const string_type >())), const value_type & > is_at_const_signature
typename std::is_same< decltype(std::declval< const object_type >().begin()), has_const_iterator< object_type > > is_begin_const_signature
typename traits_type::key_type has_key_type
typename std::is_same< decltype(std::declval< object_type >().end()), has_iterator< object_type > > is_end_signature
typename traits_type::value_type has_value_type
typename std::is_same< as_integer_function< traits_type >, integer_type(const value_type &)> is_as_integer_signature
typename object_type::iterator has_iterator
typename object_type::const_iterator has_const_iterator
typename std::is_same< get_type_function< traits_type >, json::type(const value_type &)> is_get_type_signature
typename std::is_same< as_array_function< traits_type >, array_type(const value_type &)> is_as_array_signature
typename std::is_same< decltype(std::declval< string_type >().substr(std::declval< integer_type >())), string_type > is_substr_start_index_signature
decltype(traits_type::get_type) get_type_function
decltype(traits_type::as_object) as_object_function
decltype(traits_type::as_number) as_number_function
typename std::is_same< decltype(std::declval< const object_type >().end()), has_const_iterator< object_type > > is_end_const_signature
typename std::is_integral< decltype(std::declval< const object_type >().count(std::declval< const string_type >()))> is_count_signature
typename std::is_same< decltype(std::declval< string_type >().substr(std::declval< integer_type >(), std::declval< integer_type >())), string_type > is_substr_start_end_index_signature
typename std::is_same< as_string_function< traits_type >, string_type(const value_type &)> is_as_string_signature
typename traits_type::mapped_type has_mapped_type
typename std::is_same< as_number_function< traits_type >, number_type(const value_type &)> is_as_number_signature
signature_verification_error
Errors related to verification of signatures.
@ set_rsa_pss_saltlen_failed
@ signature_encoding_failed
std::error_category & token_verification_error_category()
Error category for token verification errors.
void throw_if_error(std::error_code ec)
std::error_category & ecdsa_error_category()
Error category for ECDSA errors.
std::error_category & signature_verification_error_category()
Error category for verification errors.
std::error_category & rsa_error_category()
Error category for RSA errors.
std::error_category & signature_generation_error_category()
Error category for signature generation errors.
ecdsa_error
Errors related to processing of RSA signatures.
rsa_error
Errors related to processing of RSA signatures.
signature_generation_error
Errors related to signature generation errors.
@ set_rsa_pss_saltlen_failed
@ rsa_private_encrypt_failed
@ signature_decoding_failed
token_verification_error
Errors related to token verification errors.
std::error_code make_error_code(rsa_error e)
std::shared_ptr< EVP_PKEY > load_private_ec_key_from_string(const std::string &key, const std::string &password, std::error_code &ec)
Load a private key from a string.
std::shared_ptr< EVP_PKEY > load_private_key_from_string(const std::string &key, const std::string &password, std::error_code &ec)
Load a private key from a string.
std::shared_ptr< EVP_PKEY > load_public_ec_key_from_string(const std::string &key, const std::string &password, std::error_code &ec)
Load a public key from a string.
std::shared_ptr< EVP_PKEY > load_public_key_from_string(const std::string &key, const std::string &password, std::error_code &ec)
Load a public key from a string.
std::string extract_pubkey_from_cert(const std::string &certstr, const std::string &pw, std::error_code &ec)
Extract the public key of a pem certificate.
std::string convert_base64_der_to_pem(const std::string &cert_base64_der_str, Decode decode, std::error_code &ec)
Convert the certificate provided as base64 DER to PEM.
std::string bn2raw(const BIGNUM *bn)
std::unique_ptr< BIGNUM, decltype(&BN_free)> raw2bn(const std::string &raw)
type
Generic JSON types used in JWTs.
verifier< Clock, json_traits > verify(Clock c)
jwk< json_traits > parse_jwk(const typename json_traits::string_type &token)
jwks< json_traits > parse_jwks(const typename json_traits::string_type &token)
std::chrono::system_clock::time_point date
decoded_jwt< json_traits > decode(const typename json_traits::string_type &token, Decode decode)
builder< json_traits > create()
Base class for ECDSA family of algorithms.
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
std::string sign(const std::string &data, std::error_code &ec) const
ecdsa(const std::string &public_key, const std::string &private_key, const std::string &public_key_password, const std::string &private_key_password, const EVP_MD *(*md)(), std::string name, size_t siglen)
ed25519(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
ed448(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Base class for EdDSA family of algorithms.
eddsa(const std::string &public_key, const std::string &private_key, const std::string &public_key_password, const std::string &private_key_password, std::string name)
std::string sign(const std::string &data, std::error_code &ec) const
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
es256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
es256k(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
es384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
es512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Base class for HMAC family of algorithms.
std::string sign(const std::string &data, std::error_code &ec) const
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
hmacsha(std::string key, const EVP_MD *(*md)(), std::string name)
void verify(const std::string &, const std::string &signature, std::error_code &ec) const
Check if the given signature is empty.
std::string name() const
Get algorithm name.
std::string sign(const std::string &, std::error_code &ec) const
Return an empty string.
ps256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
ps384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
ps512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Base class for PSS-RSA family of algorithms.
pss(const std::string &public_key, const std::string &private_key, const std::string &public_key_password, const std::string &private_key_password, const EVP_MD *(*md)(), std::string name)
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
std::string sign(const std::string &data, std::error_code &ec) const
rs256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
rs384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
rs512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Base class for RSA family of algorithms.
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
std::string sign(const std::string &data, std::error_code &ec) const
rsa(const std::string &public_key, const std::string &private_key, const std::string &public_key_password, const std::string &private_key_password, const EVP_MD *(*md)(), std::string name)
static auto test_operator_plus(int) -> sfinae_true< decltype(std::declval< T >().operator+(std::declval< A0 >()))>
static auto test_operator_plus(long) -> std::false_type
static constexpr auto value
static constexpr auto value
static auto test_operator_plus(int) -> sfinae_true< decltype(std::declval< T >().operator[](std::declval< A0 >()))>
static auto test_operator_plus(long) -> std::false_type
static constexpr auto value
static constexpr auto has_subscription_operator
static constexpr auto value
static constexpr auto supports_claims_transform
static constexpr auto value
static constexpr auto operator_plus
static constexpr auto substr
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
nonesuch(nonesuch const &&)=delete
void operator=(nonesuch &&)=delete
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
static constexpr auto value
claim_not_present_exception()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
const basic_claim< json_traits > expected
insensitive_string_claim(const typename json_traits::string_type &e, std::locale loc)
static std::string to_lower_unicode(const std::string &str, const std::locale &loc)
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
const json_traits::string_type expected
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
const basic_claim< json_traits >::set_t expected
basic_claim< json_traits > get_claim(bool in_header, json::type t, std::error_code &ec) const
basic_claim< json_traits > get_claim(bool in_header, std::error_code &ec) const
verify_context(date ctime, const decoded_jwt< json_traits > &j, size_t l)
basic_claim< json_traits > get_claim(json::type t, std::error_code &ec) const
basic_claim< json_traits > get_claim(std::error_code &ec) const
const decoded_jwt< json_traits > & jwt