Goby3  3.1.4
2024.02.22
jwt.h
Go to the documentation of this file.
1 #ifndef JWT_CPP_JWT_H
2 #define JWT_CPP_JWT_H
3 
4 #ifndef JWT_DISABLE_PICOJSON
5 #ifndef PICOJSON_USE_INT64
6 #define PICOJSON_USE_INT64
7 #endif
8 #include "goby/util/thirdparty/jwt-cpp/picojson/picojson.h"
9 #endif
10 
11 #ifndef JWT_DISABLE_BASE64
12 #include "base.h"
13 #endif
14 
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>
22 
23 #include <algorithm>
24 #include <chrono>
25 #include <codecvt>
26 #include <functional>
27 #include <iterator>
28 #include <locale>
29 #include <memory>
30 #include <set>
31 #include <system_error>
32 #include <type_traits>
33 #include <unordered_map>
34 #include <utility>
35 #include <vector>
36 
37 #if __cplusplus >= 201402L
38 #ifdef __has_include
39 #if __has_include(<experimental/type_traits>)
40 #include <experimental/type_traits>
41 #endif
42 #endif
43 #endif
44 
45 #if OPENSSL_VERSION_NUMBER >= 0x30000000L // 3.0.0
46 #define JWT_OPENSSL_3_0
47 #elif OPENSSL_VERSION_NUMBER >= 0x10101000L // 1.1.1
48 #define JWT_OPENSSL_1_1_1
49 #elif OPENSSL_VERSION_NUMBER >= 0x10100000L // 1.1.0
50 #define JWT_OPENSSL_1_1_0
51 #elif OPENSSL_VERSION_NUMBER >= 0x10000000L // 1.0.0
52 #define JWT_OPENSSL_1_0_0
53 #endif
54 
55 #if defined(LIBRESSL_VERSION_NUMBER)
56 #define JWT_OPENSSL_1_0_0
57 #endif
58 
59 #if defined(LIBWOLFSSL_VERSION_HEX)
60 #define JWT_OPENSSL_1_1_1
61 #endif
62 
63 #ifndef JWT_CLAIM_EXPLICIT
64 #define JWT_CLAIM_EXPLICIT explicit
65 #endif
66 
74 namespace jwt
75 {
79 using date = std::chrono::system_clock::time_point;
80 
84 namespace error
85 {
86 struct signature_verification_exception : public std::system_error
87 {
88  using system_error::system_error;
89 };
90 struct signature_generation_exception : public std::system_error
91 {
92  using system_error::system_error;
93 };
94 struct rsa_exception : public std::system_error
95 {
96  using system_error::system_error;
97 };
98 struct ecdsa_exception : public std::system_error
99 {
100  using system_error::system_error;
101 };
102 struct token_verification_exception : public std::system_error
103 {
104  using system_error::system_error;
105 };
109 enum class rsa_error
110 {
111  ok = 0,
112  cert_load_failed = 10,
121 };
125 inline std::error_category& rsa_error_category()
126 {
127  class rsa_error_cat : public std::error_category
128  {
129  public:
130  const char* name() const noexcept override { return "rsa_error"; };
131  std::string message(int ev) const override
132  {
133  switch (static_cast<rsa_error>(ev))
134  {
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";
145  return "at least one of public or private key need to be present";
146  default: return "unknown RSA error";
147  }
148  }
149  };
150  static rsa_error_cat cat;
151  return cat;
152 }
153 
154 inline std::error_code make_error_code(rsa_error e)
155 {
156  return {static_cast<int>(e), rsa_error_category()};
157 }
161 enum class ecdsa_error
162 {
163  ok = 0,
164  load_key_bio_write = 10,
169  invalid_key,
171 };
175 inline std::error_category& ecdsa_error_category()
176 {
177  class ecdsa_error_cat : public std::error_category
178  {
179  public:
180  const char* name() const noexcept override { return "ecdsa_error"; };
181  std::string message(int ev) const override
182  {
183  switch (static_cast<ecdsa_error>(ev))
184  {
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";
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";
195  }
196  }
197  };
198  static ecdsa_error_cat cat;
199  return cat;
200 }
201 
202 inline std::error_code make_error_code(ecdsa_error e)
203 {
204  return {static_cast<int>(e), ecdsa_error_category()};
205 }
206 
211 {
212  ok = 0,
213  invalid_signature = 10,
221 };
225 inline std::error_category& signature_verification_error_category()
226 {
227  class verification_error_cat : public std::error_category
228  {
229  public:
230  const char* name() const noexcept override { return "signature_verification_error"; };
231  std::string message(int ev) const override
232  {
233  switch (static_cast<signature_verification_error>(ev))
234  {
235  case signature_verification_error::ok: return "no error";
236  case signature_verification_error::invalid_signature: return "invalid signature";
238  return "failed to verify signature: could not create context";
240  return "failed to verify signature: VerifyInit failed";
242  return "failed to verify signature: VerifyUpdate failed";
244  return "failed to verify signature: VerifyFinal failed";
246  return "failed to verify signature: Could not get key";
248  return "failed to verify signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
250  return "failed to verify signature: i2d_ECDSA_SIG failed";
251  default: return "unknown signature verification error";
252  }
253  }
254  };
255  static verification_error_cat cat;
256  return cat;
257 }
258 
260 {
261  return {static_cast<int>(e), signature_verification_error_category()};
262 }
263 
268 {
269  ok = 0,
270  hmac_failed = 10,
284 };
288 inline std::error_category& signature_generation_error_category()
289 {
290  class signature_generation_error_cat : public std::error_category
291  {
292  public:
293  const char* name() const noexcept override { return "signature_generation_error"; };
294  std::string message(int ev) const override
295  {
296  switch (static_cast<signature_generation_error>(ev))
297  {
298  case signature_generation_error::ok: return "no error";
299  case signature_generation_error::hmac_failed: return "hmac failed";
301  return "failed to create signature: could not create context";
303  return "failed to create signature: SignInit failed";
305  return "failed to create signature: SignUpdate failed";
307  return "failed to create signature: SignFinal failed";
309  return "failed to generate ecdsa signature";
311  return "failed to create signature: DigestInit failed";
313  return "failed to create signature: DigestUpdate failed";
315  return "failed to create signature: DigestFinal failed";
317  return "failed to create signature: EVP_PKEY_CTX_set_rsa_padding failed";
319  return "failed to create signature: RSA_private_encrypt failed";
321  return "failed to generate signature: Could not get key";
323  return "failed to create signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
325  return "failed to create signature: d2i_ECDSA_SIG failed";
326  default: return "unknown signature generation error";
327  }
328  }
329  };
330  static signature_generation_error_cat cat = {};
331  return cat;
332 }
333 
335 {
336  return {static_cast<int>(e), signature_generation_error_category()};
337 }
338 
343 {
344  ok = 0,
345  wrong_algorithm = 10,
351 };
355 inline std::error_category& token_verification_error_category()
356 {
357  class token_verification_error_cat : public std::error_category
358  {
359  public:
360  const char* name() const noexcept override { return "token_verification_error"; };
361  std::string message(int ev) const override
362  {
363  switch (static_cast<token_verification_error>(ev))
364  {
365  case token_verification_error::ok: return "no error";
366  case token_verification_error::wrong_algorithm: return "wrong algorithm";
368  return "decoded JWT is missing required claim(s)";
370  return "claim type does not match expected type";
372  return "claim value does not match expected value";
373  case token_verification_error::token_expired: return "token expired";
375  return "token doesn't contain the required audience";
376  default: return "unknown token verification error";
377  }
378  }
379  };
380  static token_verification_error_cat cat = {};
381  return cat;
382 }
383 
385 {
386  return {static_cast<int>(e), token_verification_error_category()};
387 }
388 
389 inline void throw_if_error(std::error_code ec)
390 {
391  if (ec)
392  {
393  if (ec.category() == rsa_error_category())
394  throw rsa_exception(ec);
395  if (ec.category() == ecdsa_error_category())
396  throw ecdsa_exception(ec);
397  if (ec.category() == signature_verification_error_category())
399  if (ec.category() == signature_generation_error_category())
401  if (ec.category() == token_verification_error_category())
403  }
404 }
405 } // namespace error
406 
407 // FIXME: Remove
408 // Keep backward compat at least for a couple of revisions
409 using error::ecdsa_exception;
410 using error::rsa_exception;
411 using error::signature_generation_exception;
412 using error::signature_verification_exception;
413 using error::token_verification_exception;
414 } // namespace jwt
415 namespace std
416 {
417 template <> struct is_error_code_enum<jwt::error::rsa_error> : true_type
418 {
419 };
420 template <> struct is_error_code_enum<jwt::error::ecdsa_error> : true_type
421 {
422 };
423 template <> struct is_error_code_enum<jwt::error::signature_verification_error> : true_type
424 {
425 };
426 template <> struct is_error_code_enum<jwt::error::signature_generation_error> : true_type
427 {
428 };
429 template <> struct is_error_code_enum<jwt::error::token_verification_error> : true_type
430 {
431 };
432 } // namespace std
433 namespace jwt
434 {
442 namespace helper
443 {
451 inline std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw,
452  std::error_code& ec)
453 {
454  ec.clear();
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())),
458  BIO_free_all);
459 #else
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);
462 #endif
463  std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all);
464  if (!certbio || !keybio)
465  {
467  return {};
468  }
469 
470  std::unique_ptr<X509, decltype(&X509_free)> cert(
471  PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())),
472  X509_free);
473  if (!cert)
474  {
476  return {};
477  }
478  std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()),
479  EVP_PKEY_free);
480  if (!key)
481  {
483  return {};
484  }
485  if (PEM_write_bio_PUBKEY(keybio.get(), key.get()) == 0)
486  {
488  return {};
489  }
490  char* ptr = nullptr;
491  auto len = BIO_get_mem_data(keybio.get(), &ptr);
492  if (len <= 0 || ptr == nullptr)
493  {
495  return {};
496  }
497  return {ptr, static_cast<size_t>(len)};
498 }
499 
507 inline std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw = "")
508 {
509  std::error_code ec;
510  auto res = extract_pubkey_from_cert(certstr, pw, ec);
512  return res;
513 }
514 
529 template <typename Decode>
530 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode,
531  std::error_code& ec)
532 {
533  ec.clear();
534  const auto decodedStr = decode(cert_base64_der_str);
535  auto c_str = reinterpret_cast<const unsigned char*>(decodedStr.c_str());
536 
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)
541  {
543  return {};
544  }
545 
546  if (!PEM_write_bio_X509(certbio.get(), cert.get()))
547  {
549  return {};
550  }
551 
552  char* ptr = nullptr;
553  const auto len = BIO_get_mem_data(certbio.get(), &ptr);
554  if (len <= 0 || ptr == nullptr)
555  {
557  return {};
558  }
559 
560  return {ptr, static_cast<size_t>(len)};
561 }
562 
577 template <typename Decode>
578 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode)
579 {
580  std::error_code ec;
581  auto res = convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
583  return res;
584 }
585 #ifndef JWT_DISABLE_BASE64
586 
595 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str,
596  std::error_code& ec)
597 {
598  auto decode = [](const std::string& token)
599  { return base::decode<alphabet::base64>(base::pad<alphabet::base64>(token)); };
600  return convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
601 }
602 
612 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str)
613 {
614  std::error_code ec;
615  auto res = convert_base64_der_to_pem(cert_base64_der_str, ec);
617  return res;
618 }
619 #endif
620 
629 inline std::shared_ptr<EVP_PKEY> load_public_key_from_string(const std::string& key,
630  const std::string& password,
631  std::error_code& ec)
632 {
633  ec.clear();
634  std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
635  if (!pubkey_bio)
636  {
638  return nullptr;
639  }
640  if (key.substr(0, 27) == "-----BEGIN CERTIFICATE-----")
641  {
642  auto epkey = helper::extract_pubkey_from_cert(key, password, ec);
643  if (ec)
644  return nullptr;
645  const int len = static_cast<int>(epkey.size());
646  if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len)
647  {
649  return nullptr;
650  }
651  }
652  else
653  {
654  const int len = static_cast<int>(key.size());
655  if (BIO_write(pubkey_bio.get(), key.data(), len) != len)
656  {
658  return nullptr;
659  }
660  }
661 
662  std::shared_ptr<EVP_PKEY> pkey(
663  PEM_read_bio_PUBKEY(
664  pubkey_bio.get(), nullptr, nullptr,
665  (void*)password.data()), // NOLINT(google-readability-casting) requires `const_cast`
666  EVP_PKEY_free);
667  if (!pkey)
668  {
670  return nullptr;
671  }
672  return pkey;
673 }
674 
684 inline std::shared_ptr<EVP_PKEY> load_public_key_from_string(const std::string& key,
685  const std::string& password = "")
686 {
687  std::error_code ec;
688  auto res = load_public_key_from_string(key, password, ec);
690  return res;
691 }
692 
700 inline std::shared_ptr<EVP_PKEY> load_private_key_from_string(const std::string& key,
701  const std::string& password,
702  std::error_code& ec)
703 {
704  std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
705  if (!privkey_bio)
706  {
708  return nullptr;
709  }
710  const int len = static_cast<int>(key.size());
711  if (BIO_write(privkey_bio.get(), key.data(), len) != len)
712  {
714  return nullptr;
715  }
716  std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(privkey_bio.get(), nullptr, nullptr,
717  const_cast<char*>(password.c_str())),
718  EVP_PKEY_free);
719  if (!pkey)
720  {
722  return nullptr;
723  }
724  return pkey;
725 }
726 
734 inline std::shared_ptr<EVP_PKEY> load_private_key_from_string(const std::string& key,
735  const std::string& password = "")
736 {
737  std::error_code ec;
738  auto res = load_private_key_from_string(key, password, ec);
740  return res;
741 }
742 
752 inline std::shared_ptr<EVP_PKEY> load_public_ec_key_from_string(const std::string& key,
753  const std::string& password,
754  std::error_code& ec)
755 {
756  ec.clear();
757  std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
758  if (!pubkey_bio)
759  {
761  return nullptr;
762  }
763  if (key.substr(0, 27) == "-----BEGIN CERTIFICATE-----")
764  {
765  auto epkey = helper::extract_pubkey_from_cert(key, password, ec);
766  if (ec)
767  return nullptr;
768  const int len = static_cast<int>(epkey.size());
769  if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len)
770  {
772  return nullptr;
773  }
774  }
775  else
776  {
777  const int len = static_cast<int>(key.size());
778  if (BIO_write(pubkey_bio.get(), key.data(), len) != len)
779  {
781  return nullptr;
782  }
783  }
784 
785  std::shared_ptr<EVP_PKEY> pkey(
786  PEM_read_bio_PUBKEY(
787  pubkey_bio.get(), nullptr, nullptr,
788  (void*)password.data()), // NOLINT(google-readability-casting) requires `const_cast`
789  EVP_PKEY_free);
790  if (!pkey)
791  {
793  return nullptr;
794  }
795  return pkey;
796 }
797 
807 inline std::shared_ptr<EVP_PKEY> load_public_ec_key_from_string(const std::string& key,
808  const std::string& password = "")
809 {
810  std::error_code ec;
811  auto res = load_public_ec_key_from_string(key, password, ec);
813  return res;
814 }
815 
823 inline std::shared_ptr<EVP_PKEY> load_private_ec_key_from_string(const std::string& key,
824  const std::string& password,
825  std::error_code& ec)
826 {
827  std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
828  if (!privkey_bio)
829  {
831  return nullptr;
832  }
833  const int len = static_cast<int>(key.size());
834  if (BIO_write(privkey_bio.get(), key.data(), len) != len)
835  {
837  return nullptr;
838  }
839  std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(privkey_bio.get(), nullptr, nullptr,
840  const_cast<char*>(password.c_str())),
841  EVP_PKEY_free);
842  if (!pkey)
843  {
845  return nullptr;
846  }
847  return pkey;
848 }
849 
857 inline std::shared_ptr<EVP_PKEY> load_private_ec_key_from_string(const std::string& key,
858  const std::string& password = "")
859 {
860  std::error_code ec;
861  auto res = load_private_ec_key_from_string(key, password, ec);
863  return res;
864 }
865 
871 inline
872 #ifdef JWT_OPENSSL_1_0_0
873  std::string
874  bn2raw(BIGNUM* bn)
875 #else
876  std::string
877  bn2raw(const BIGNUM* bn)
878 #endif
879 {
880  std::string res(BN_num_bytes(bn), '\0');
881  BN_bn2bin(
882  bn, (unsigned char*)res.data()); // NOLINT(google-readability-casting) requires `const_cast`
883  return res;
884 }
890 inline std::unique_ptr<BIGNUM, decltype(&BN_free)> raw2bn(const std::string& raw)
891 {
892  return std::unique_ptr<BIGNUM, decltype(&BN_free)>(
893  BN_bin2bn(reinterpret_cast<const unsigned char*>(raw.data()), static_cast<int>(raw.size()),
894  nullptr),
895  BN_free);
896 }
897 } // namespace helper
898 
908 namespace algorithm
909 {
915 struct none
916 {
920  std::string sign(const std::string& /*unused*/, std::error_code& ec) const
921  {
922  ec.clear();
923  return {};
924  }
932  void verify(const std::string& /*unused*/, const std::string& signature,
933  std::error_code& ec) const
934  {
935  ec.clear();
936  if (!signature.empty())
937  {
939  }
940  }
942  std::string name() const { return "none"; }
943 };
947 struct hmacsha
948 {
955  hmacsha(std::string key, const EVP_MD* (*md)(), std::string name)
956  : secret(std::move(key)), md(md), alg_name(std::move(name))
957  {
958  }
965  std::string sign(const std::string& data, std::error_code& ec) const
966  {
967  ec.clear();
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()),
972  (unsigned char*)
973  res.data(), // NOLINT(google-readability-casting) requires `const_cast`
974  &len) == nullptr)
975  {
977  return {};
978  }
979  res.resize(len);
980  return res;
981  }
988  void verify(const std::string& data, const std::string& signature, std::error_code& ec) const
989  {
990  ec.clear();
991  auto res = sign(data, ec);
992  if (ec)
993  return;
994 
995  bool matched = true;
996  for (size_t i = 0; i < std::min<size_t>(res.size(), signature.size()); i++)
997  if (res[i] != signature[i])
998  matched = false;
999  if (res.size() != signature.size())
1000  matched = false;
1001  if (!matched)
1002  {
1004  return;
1005  }
1006  }
1011  std::string name() const { return alg_name; }
1012 
1013  private:
1015  const std::string secret;
1017  const EVP_MD* (*md)();
1019  const std::string alg_name;
1020 };
1024 struct rsa
1025 {
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))
1039  {
1040  if (!private_key.empty())
1041  {
1042  pkey = helper::load_private_key_from_string(private_key, private_key_password);
1043  }
1044  else if (!public_key.empty())
1045  {
1046  pkey = helper::load_public_key_from_string(public_key, public_key_password);
1047  }
1048  else
1050  }
1057  std::string sign(const std::string& data, std::error_code& ec) const
1058  {
1059  ec.clear();
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);
1063 #else
1064  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1065  EVP_MD_CTX_free);
1066 #endif
1067  if (!ctx)
1068  {
1070  return {};
1071  }
1072  if (!EVP_SignInit(ctx.get(), md()))
1073  {
1075  return {};
1076  }
1077 
1078  std::string res(EVP_PKEY_size(pkey.get()), '\0');
1079  unsigned int len = 0;
1080 
1081  if (!EVP_SignUpdate(ctx.get(), data.data(), data.size()))
1082  {
1084  return {};
1085  }
1086  if (EVP_SignFinal(ctx.get(), (unsigned char*)res.data(), &len, pkey.get()) == 0)
1087  {
1089  return {};
1090  }
1091 
1092  res.resize(len);
1093  return res;
1094  }
1101  void verify(const std::string& data, const std::string& signature, std::error_code& ec) const
1102  {
1103  ec.clear();
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);
1107 #else
1108  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1109  EVP_MD_CTX_free);
1110 #endif
1111  if (!ctx)
1112  {
1114  return;
1115  }
1116  if (!EVP_VerifyInit(ctx.get(), md()))
1117  {
1119  return;
1120  }
1121  if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size()))
1122  {
1124  return;
1125  }
1126  auto res =
1127  EVP_VerifyFinal(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1128  static_cast<unsigned int>(signature.size()), pkey.get());
1129  if (res != 1)
1130  {
1132  return;
1133  }
1134  }
1139  std::string name() const { return alg_name; }
1140 
1141  private:
1143  std::shared_ptr<EVP_PKEY> pkey;
1145  const EVP_MD* (*md)();
1147  const std::string alg_name;
1148 };
1152 struct ecdsa
1153 {
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)
1169  {
1170  if (!private_key.empty())
1171  {
1172  pkey = helper::load_private_ec_key_from_string(private_key, private_key_password);
1173  check_private_key(pkey.get());
1174  }
1175  else if (!public_key.empty())
1176  {
1177  pkey = helper::load_public_ec_key_from_string(public_key, public_key_password);
1178  check_public_key(pkey.get());
1179  }
1180  else
1181  {
1183  }
1184  if (!pkey)
1186 
1187  size_t keysize = EVP_PKEY_bits(pkey.get());
1188  if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
1190  }
1191 
1198  std::string sign(const std::string& data, std::error_code& ec) const
1199  {
1200  ec.clear();
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);
1204 #else
1205  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1206  EVP_MD_CTX_free);
1207 #endif
1208  if (!ctx)
1209  {
1211  return {};
1212  }
1213  if (!EVP_DigestSignInit(ctx.get(), nullptr, md(), nullptr, pkey.get()))
1214  {
1216  return {};
1217  }
1218  if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size()))
1219  {
1221  return {};
1222  }
1223 
1224  size_t len = 0;
1225  if (!EVP_DigestSignFinal(ctx.get(), nullptr, &len))
1226  {
1228  return {};
1229  }
1230  std::string res(len, '\0');
1231  if (!EVP_DigestSignFinal(ctx.get(), (unsigned char*)res.data(), &len))
1232  {
1234  return {};
1235  }
1236 
1237  res.resize(len);
1238  return der_to_p1363_signature(res, ec);
1239  }
1240 
1247  void verify(const std::string& data, const std::string& signature, std::error_code& ec) const
1248  {
1249  ec.clear();
1250  std::string der_signature = p1363_to_der_signature(signature, ec);
1251  if (ec)
1252  {
1253  return;
1254  }
1255 
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);
1259 #else
1260  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(),
1261  EVP_MD_CTX_free);
1262 #endif
1263  if (!ctx)
1264  {
1266  return;
1267  }
1268  if (!EVP_DigestVerifyInit(ctx.get(), nullptr, md(), nullptr, pkey.get()))
1269  {
1271  return;
1272  }
1273  if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size()))
1274  {
1276  return;
1277  }
1278 
1279 #if OPENSSL_VERSION_NUMBER < 0x10002000L
1280  unsigned char* der_sig_data =
1281  reinterpret_cast<unsigned char*>(const_cast<char*>(der_signature.data()));
1282 #else
1283  const unsigned char* der_sig_data =
1284  reinterpret_cast<const unsigned char*>(der_signature.data());
1285 #endif
1286  auto res = EVP_DigestVerifyFinal(ctx.get(), der_sig_data,
1287  static_cast<unsigned int>(der_signature.length()));
1288  if (res == 0)
1289  {
1291  return;
1292  }
1293  if (res == -1)
1294  {
1296  return;
1297  }
1298  }
1303  std::string name() const { return alg_name; }
1304 
1305  private:
1306  static void check_public_key(EVP_PKEY* pkey)
1307  {
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);
1311  if (!ctx)
1312  {
1314  }
1315  if (EVP_PKEY_public_check(ctx.get()) != 1)
1316  {
1318  }
1319 #else
1320  std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey),
1321  EC_KEY_free);
1322  if (!eckey)
1323  {
1324  throw ecdsa_exception(error::ecdsa_error::invalid_key);
1325  }
1326  if (EC_KEY_check_key(eckey.get()) == 0)
1327  throw ecdsa_exception(error::ecdsa_error::invalid_key);
1328 #endif
1329  }
1330 
1331  static void check_private_key(EVP_PKEY* pkey)
1332  {
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);
1336  if (!ctx)
1337  {
1338  throw ecdsa_exception(error::ecdsa_error::create_context_failed);
1339  }
1340  if (EVP_PKEY_private_check(ctx.get()) != 1)
1341  {
1342  throw ecdsa_exception(error::ecdsa_error::invalid_key);
1343  }
1344 #else
1345  std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey),
1346  EC_KEY_free);
1347  if (!eckey)
1348  {
1349  throw ecdsa_exception(error::ecdsa_error::invalid_key);
1350  }
1351  if (EC_KEY_check_key(eckey.get()) == 0)
1352  throw ecdsa_exception(error::ecdsa_error::invalid_key);
1353 #endif
1354  }
1355 
1356  std::string der_to_p1363_signature(const std::string& der_signature, std::error_code& ec) const
1357  {
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);
1362  if (!sig)
1363  {
1365  return {};
1366  }
1367 
1368 #ifdef JWT_OPENSSL_1_0_0
1369 
1370  auto rr = helper::bn2raw(sig->r);
1371  auto rs = helper::bn2raw(sig->s);
1372 #else
1373  const BIGNUM* r;
1374  const BIGNUM* s;
1375  ECDSA_SIG_get0(sig.get(), &r, &s);
1376  auto rr = helper::bn2raw(r);
1377  auto rs = helper::bn2raw(s);
1378 #endif
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');
1383  return rr + rs;
1384  }
1385 
1386  std::string p1363_to_der_signature(const std::string& signature, std::error_code& ec) const
1387  {
1388  ec.clear();
1389  auto r = helper::raw2bn(signature.substr(0, signature.size() / 2));
1390  auto s = helper::raw2bn(signature.substr(signature.size() / 2));
1391 
1392  ECDSA_SIG* psig;
1393 #ifdef JWT_OPENSSL_1_0_0
1394  ECDSA_SIG sig;
1395  sig.r = r.get();
1396  sig.s = s.get();
1397  psig = &sig;
1398 #else
1399  std::unique_ptr<ECDSA_SIG, decltype(&ECDSA_SIG_free)> sig(ECDSA_SIG_new(), ECDSA_SIG_free);
1400  if (!sig)
1401  {
1403  return {};
1404  }
1405  ECDSA_SIG_set0(sig.get(), r.release(), s.release());
1406  psig = sig.get();
1407 #endif
1408 
1409  int length = i2d_ECDSA_SIG(psig, nullptr);
1410  if (length < 0)
1411  {
1413  return {};
1414  }
1415  std::string der_signature(length, '\0');
1416  unsigned char* psbuffer = (unsigned char*)der_signature.data();
1417  length = i2d_ECDSA_SIG(psig, &psbuffer);
1418  if (length < 0)
1419  {
1421  return {};
1422  }
1423  der_signature.resize(length);
1424  return der_signature;
1425  }
1426 
1428  std::shared_ptr<EVP_PKEY> pkey;
1430  const EVP_MD* (*md)();
1432  const std::string alg_name;
1434  const size_t signature_length;
1435 };
1436 
1437 #if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1438 
1446 struct eddsa
1447 {
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,
1460  std::string name)
1461  : alg_name(std::move(name))
1462  {
1463  if (!private_key.empty())
1464  {
1465  pkey = helper::load_private_key_from_string(private_key, private_key_password);
1466  }
1467  else if (!public_key.empty())
1468  {
1469  pkey = helper::load_public_key_from_string(public_key, public_key_password);
1470  }
1471  else
1473  }
1480  std::string sign(const std::string& data, std::error_code& ec) const
1481  {
1482  ec.clear();
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);
1486 #else
1487  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(),
1488  EVP_MD_CTX_free);
1489 #endif
1490  if (!ctx)
1491  {
1493  return {};
1494  }
1495  if (!EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get()))
1496  {
1498  return {};
1499  }
1500 
1501  size_t len = EVP_PKEY_size(pkey.get());
1502  std::string res(len, '\0');
1503 
1504 // LibreSSL is the special kid in the block, as it does not support EVP_DigestSign.
1505 // OpenSSL on the otherhand does not support using EVP_DigestSignUpdate for eddsa, which is why we end up with this
1506 // mess.
1507 #if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1508  ERR_clear_error();
1509  if (EVP_DigestSignUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()),
1510  data.size()) != 1)
1511  {
1512  std::cout << ERR_error_string(ERR_get_error(), NULL) << std::endl;
1514  return {};
1515  }
1516  if (EVP_DigestSignFinal(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len) != 1)
1517  {
1519  return {};
1520  }
1521 #else
1522  if (EVP_DigestSign(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len,
1523  reinterpret_cast<const unsigned char*>(data.data()), data.size()) != 1)
1524  {
1526  return {};
1527  }
1528 #endif
1529 
1530  res.resize(len);
1531  return res;
1532  }
1533 
1540  void verify(const std::string& data, const std::string& signature, std::error_code& ec) const
1541  {
1542  ec.clear();
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);
1546 #else
1547  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(),
1548  EVP_MD_CTX_free);
1549 #endif
1550  if (!ctx)
1551  {
1553  return;
1554  }
1555  if (!EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get()))
1556  {
1558  return;
1559  }
1560 // LibreSSL is the special kid in the block, as it does not support EVP_DigestVerify.
1561 // OpenSSL on the otherhand does not support using EVP_DigestVerifyUpdate for eddsa, which is why we end up with this
1562 // mess.
1563 #if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1564  if (EVP_DigestVerifyUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()),
1565  data.size()) != 1)
1566  {
1568  return;
1569  }
1570  if (EVP_DigestVerifyFinal(ctx.get(),
1571  reinterpret_cast<const unsigned char*>(signature.data()),
1572  signature.size()) != 1)
1573  {
1575  return;
1576  }
1577 #else
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());
1581  if (res != 1)
1582  {
1584  return;
1585  }
1586 #endif
1587  }
1592  std::string name() const { return alg_name; }
1593 
1594  private:
1596  std::shared_ptr<EVP_PKEY> pkey;
1598  const std::string alg_name;
1599 };
1600 #endif
1601 
1604 struct pss
1605 {
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))
1619  {
1620  if (!private_key.empty())
1621  {
1622  pkey = helper::load_private_key_from_string(private_key, private_key_password);
1623  }
1624  else if (!public_key.empty())
1625  {
1626  pkey = helper::load_public_key_from_string(public_key, public_key_password);
1627  }
1628  else
1630  }
1631 
1638  std::string sign(const std::string& data, std::error_code& ec) const
1639  {
1640  ec.clear();
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);
1644 #else
1645  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(),
1646  EVP_MD_CTX_free);
1647 #endif
1648  if (!md_ctx)
1649  {
1651  return {};
1652  }
1653  EVP_PKEY_CTX* ctx = nullptr;
1654  if (EVP_DigestSignInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1)
1655  {
1657  return {};
1658  }
1659  if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
1660  {
1662  return {};
1663  }
1664 // wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
1665 // sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
1666 #ifndef LIBWOLFSSL_VERSION_HEX
1667  if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
1668  {
1670  return {};
1671  }
1672 #endif
1673  if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1)
1674  {
1676  return {};
1677  }
1678 
1679  size_t size = EVP_PKEY_size(pkey.get());
1680  std::string res(size, 0x00);
1681  if (EVP_DigestSignFinal(
1682  md_ctx.get(),
1683  (unsigned char*)
1684  res.data(), // NOLINT(google-readability-casting) requires `const_cast`
1685  &size) <= 0)
1686  {
1688  return {};
1689  }
1690 
1691  return res;
1692  }
1693 
1700  void verify(const std::string& data, const std::string& signature, std::error_code& ec) const
1701  {
1702  ec.clear();
1703 
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);
1707 #else
1708  std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(),
1709  EVP_MD_CTX_free);
1710 #endif
1711  if (!md_ctx)
1712  {
1714  return;
1715  }
1716  EVP_PKEY_CTX* ctx = nullptr;
1717  if (EVP_DigestVerifyInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1)
1718  {
1720  return;
1721  }
1722  if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0)
1723  {
1725  return;
1726  }
1727 // wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
1728 // sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
1729 #ifndef LIBWOLFSSL_VERSION_HEX
1730  if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
1731  {
1733  return;
1734  }
1735 #endif
1736  if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1)
1737  {
1739  return;
1740  }
1741 
1742  if (EVP_DigestVerifyFinal(md_ctx.get(), (unsigned char*)signature.data(),
1743  signature.size()) <= 0)
1744  {
1746  return;
1747  }
1748  }
1753  std::string name() const { return alg_name; }
1754 
1755  private:
1757  std::shared_ptr<EVP_PKEY> pkey;
1759  const EVP_MD* (*md)();
1761  const std::string alg_name;
1762 };
1763 
1767 struct hs256 : public hmacsha
1768 {
1773  explicit hs256(std::string key) : hmacsha(std::move(key), EVP_sha256, "HS256") {}
1774 };
1778 struct hs384 : public hmacsha
1779 {
1784  explicit hs384(std::string key) : hmacsha(std::move(key), EVP_sha384, "HS384") {}
1785 };
1789 struct hs512 : public hmacsha
1790 {
1795  explicit hs512(std::string key) : hmacsha(std::move(key), EVP_sha512, "HS512") {}
1796 };
1800 struct rs256 : public rsa
1801 {
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,
1813  "RS256")
1814  {
1815  }
1816 };
1820 struct rs384 : public rsa
1821 {
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,
1833  "RS384")
1834  {
1835  }
1836 };
1840 struct rs512 : public rsa
1841 {
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,
1853  "RS512")
1854  {
1855  }
1856 };
1860 struct es256 : public ecdsa
1861 {
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,
1875  "ES256", 64)
1876  {
1877  }
1878 };
1882 struct es384 : public ecdsa
1883 {
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,
1897  "ES384", 96)
1898  {
1899  }
1900 };
1904 struct es512 : public ecdsa
1905 {
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,
1919  "ES512", 132)
1920  {
1921  }
1922 };
1926 struct es256k : public ecdsa
1927 {
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,
1940  "ES256K", 64)
1941  {
1942  }
1943 };
1944 
1945 #if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1946 
1953 struct ed25519 : public eddsa
1954 {
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")
1968  {
1969  }
1970 };
1971 
1979 struct ed448 : public eddsa
1980 {
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")
1994  {
1995  }
1996 };
1997 #endif
1998 
2002 struct ps256 : public pss
2003 {
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,
2015  "PS256")
2016  {
2017  }
2018 };
2022 struct ps384 : public pss
2023 {
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,
2035  "PS384")
2036  {
2037  }
2038 };
2042 struct ps512 : public pss
2043 {
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,
2055  "PS512")
2056  {
2057  }
2058 };
2059 } // namespace algorithm
2060 
2064 namespace json
2065 {
2071 enum class type
2072 {
2073  boolean,
2074  integer,
2075  number,
2076  string,
2077  array,
2078  object
2079 };
2080 } // namespace json
2081 
2082 namespace details
2083 {
2084 #ifdef __cpp_lib_void_t
2085 template <typename... Ts> using void_t = std::void_t<Ts...>;
2086 #else
2087 // https://en.cppreference.com/w/cpp/types/void_t
2088 template <typename... Ts> struct make_void
2089 {
2090  using type = void;
2091 };
2092 
2093 template <typename... Ts> using void_t = typename make_void<Ts...>::type;
2094 #endif
2095 
2096 #ifdef __cpp_lib_experimental_detect
2097 template <template <typename...> class _Op, typename... _Args>
2098 using is_detected = std::experimental::is_detected<_Op, _Args...>;
2099 
2100 template <template <typename...> class _Op, typename... _Args>
2101 using is_detected_t = std::experimental::detected_t<_Op, _Args...>;
2102 #else
2103 struct nonesuch
2104 {
2105  nonesuch() = delete;
2106  ~nonesuch() = delete;
2107  nonesuch(nonesuch const&) = delete;
2108  nonesuch(nonesuch const&&) = delete;
2109  void operator=(nonesuch const&) = delete;
2110  void operator=(nonesuch&&) = delete;
2111 };
2112 
2113 // https://en.cppreference.com/w/cpp/experimental/is_detected
2114 template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
2115 struct detector
2116 {
2117  using value = std::false_type;
2118  using type = Default;
2119 };
2120 
2121 template <class Default, template <class...> class Op, class... Args>
2122 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2123 {
2124  using value = std::true_type;
2125  using type = Op<Args...>;
2126 };
2127 
2128 template <template <class...> class Op, class... Args>
2129 using is_detected = typename detector<nonesuch, void, Op, Args...>::value;
2130 
2131 template <template <class...> class Op, class... Args>
2132 using is_detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2133 #endif
2134 
2135 template <typename traits_type> using get_type_function = decltype(traits_type::get_type);
2136 
2137 template <typename traits_type, typename value_type>
2138 using is_get_type_signature =
2139  typename std::is_same<get_type_function<traits_type>, json::type(const value_type&)>;
2140 
2141 template <typename traits_type, typename value_type> struct supports_get_type
2142 {
2144  std::is_function<get_type_function<traits_type>>::value &&
2146 };
2147 
2148 template <typename traits_type> using as_object_function = decltype(traits_type::as_object);
2149 
2150 template <typename traits_type, typename value_type, typename object_type>
2151 using is_as_object_signature =
2152  typename std::is_same<as_object_function<traits_type>, object_type(const value_type&)>;
2153 
2154 template <typename traits_type, typename value_type, typename object_type> struct supports_as_object
2155 {
2156  static constexpr auto value =
2157  std::is_constructible<value_type, object_type>::value &&
2159  std::is_function<as_object_function<traits_type>>::value &&
2161 };
2162 
2163 template <typename traits_type> using as_array_function = decltype(traits_type::as_array);
2164 
2165 template <typename traits_type, typename value_type, typename array_type>
2166 using is_as_array_signature =
2167  typename std::is_same<as_array_function<traits_type>, array_type(const value_type&)>;
2168 
2169 template <typename traits_type, typename value_type, typename array_type> struct supports_as_array
2170 {
2171  static constexpr auto value = std::is_constructible<value_type, array_type>::value &&
2173  std::is_function<as_array_function<traits_type>>::value &&
2175 };
2176 
2177 template <typename traits_type> using as_string_function = decltype(traits_type::as_string);
2178 
2179 template <typename traits_type, typename value_type, typename string_type>
2180 using is_as_string_signature =
2181  typename std::is_same<as_string_function<traits_type>, string_type(const value_type&)>;
2182 
2183 template <typename traits_type, typename value_type, typename string_type> struct supports_as_string
2184 {
2185  static constexpr auto value =
2186  std::is_constructible<value_type, string_type>::value &&
2188  std::is_function<as_string_function<traits_type>>::value &&
2190 };
2191 
2192 template <typename traits_type> using as_number_function = decltype(traits_type::as_number);
2193 
2194 template <typename traits_type, typename value_type, typename number_type>
2195 using is_as_number_signature =
2196  typename std::is_same<as_number_function<traits_type>, number_type(const value_type&)>;
2197 
2198 template <typename traits_type, typename value_type, typename number_type> struct supports_as_number
2199 {
2200  static constexpr auto value =
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 &&
2206 };
2207 
2208 template <typename traits_type> using as_integer_function = decltype(traits_type::as_int);
2209 
2210 template <typename traits_type, typename value_type, typename integer_type>
2212  typename std::is_same<as_integer_function<traits_type>, integer_type(const value_type&)>;
2213 
2214 template <typename traits_type, typename value_type, typename integer_type>
2216 {
2217  static constexpr auto value =
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 &&
2223 };
2224 
2225 template <typename traits_type> using as_boolean_function = decltype(traits_type::as_bool);
2226 
2227 template <typename traits_type, typename value_type, typename boolean_type>
2229  typename std::is_same<as_boolean_function<traits_type>, boolean_type(const value_type&)>;
2230 
2231 template <typename traits_type, typename value_type, typename boolean_type>
2233 {
2234  static constexpr auto value =
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 &&
2240 };
2241 
2242 template <typename traits> struct is_valid_traits
2243 {
2244  // Internal assertions for better feedback
2246  "traits must provide `jwt::json::type get_type(const value_type&)`");
2247  static_assert(supports_as_object<traits, typename traits::value_type,
2248  typename traits::object_type>::value,
2249  "traits must provide `object_type as_object(const value_type&)`");
2250  static_assert(
2252  "traits must provide `array_type as_array(const value_type&)`");
2253  static_assert(supports_as_string<traits, typename traits::value_type,
2254  typename traits::string_type>::value,
2255  "traits must provide `string_type as_string(const value_type&)`");
2256  static_assert(supports_as_number<traits, typename traits::value_type,
2257  typename traits::number_type>::value,
2258  "traits must provide `number_type as_number(const value_type&)`");
2259  static_assert(supports_as_integer<traits, typename traits::value_type,
2260  typename traits::integer_type>::value,
2261  "traits must provide `integer_type as_int(const value_type&)`");
2262  static_assert(supports_as_boolean<traits, typename traits::value_type,
2263  typename traits::boolean_type>::value,
2264  "traits must provide `boolean_type as_bool(const value_type&)`");
2265 
2267  supports_as_object<traits, typename traits::value_type,
2268  typename traits::object_type>::value &&
2269  supports_as_array<traits, typename traits::value_type,
2270  typename traits::array_type>::value &&
2271  supports_as_string<traits, typename traits::value_type,
2272  typename traits::string_type>::value &&
2273  supports_as_number<traits, typename traits::value_type,
2274  typename traits::number_type>::value &&
2275  supports_as_integer<traits, typename traits::value_type,
2276  typename traits::integer_type>::value &&
2277  supports_as_boolean<traits, typename traits::value_type,
2278  typename traits::boolean_type>::value;
2279 };
2280 
2281 template <typename value_type> struct is_valid_json_value
2282 {
2283  static constexpr auto value =
2284  std::is_default_constructible<value_type>::value &&
2285  std::is_constructible<value_type,
2286  const value_type&>::value && // a more generic is_copy_constructible
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;
2290  // TODO(prince-chrismc): Stream operators
2291 };
2292 
2293 template <typename traits_type> using has_mapped_type = typename traits_type::mapped_type;
2294 
2295 template <typename traits_type> using has_key_type = typename traits_type::key_type;
2296 
2297 template <typename traits_type> using has_value_type = typename traits_type::value_type;
2298 
2299 template <typename object_type> using has_iterator = typename object_type::iterator;
2300 
2301 template <typename object_type> using has_const_iterator = typename object_type::const_iterator;
2302 
2303 template <typename object_type>
2304 using is_begin_signature =
2305  typename std::is_same<decltype(std::declval<object_type>().begin()), has_iterator<object_type>>;
2306 
2307 template <typename object_type>
2309  typename std::is_same<decltype(std::declval<const object_type>().begin()),
2311 
2312 template <typename object_type> struct supports_begin
2313 {
2318 };
2319 
2320 template <typename object_type>
2321 using is_end_signature =
2322  typename std::is_same<decltype(std::declval<object_type>().end()), has_iterator<object_type>>;
2323 
2324 template <typename object_type>
2325 using is_end_const_signature =
2326  typename std::is_same<decltype(std::declval<const object_type>().end()),
2328 
2329 template <typename object_type> struct supports_end
2330 {
2335 };
2336 
2337 template <typename object_type, typename string_type>
2338 using is_count_signature =
2339  typename std::is_integral<decltype(std::declval<const object_type>().count(
2340  std::declval<const string_type>()))>;
2341 
2342 template <typename object_type, typename string_type> struct has_subcription_operator
2343 {
2344  template <class> struct sfinae_true : std::true_type
2345  {
2346  };
2347 
2348  template <class T, class A0>
2349  static auto test_operator_plus(int)
2350  -> sfinae_true<decltype(std::declval<T>().operator[](std::declval<A0>()))>;
2351  template <class, class A0> static auto test_operator_plus(long) -> std::false_type;
2352 
2353  static constexpr auto value = decltype(test_operator_plus<object_type, string_type>(0)){};
2354 };
2355 
2356 template <typename object_type, typename value_type, typename string_type>
2358 {
2359  static constexpr auto has_subscription_operator =
2361  static_assert(has_subscription_operator,
2362  "object_type must implementate the subscription operator '[]' for this library");
2363 
2364  static constexpr auto value = has_subscription_operator;
2365 };
2366 
2367 template <typename object_type, typename value_type, typename string_type>
2368 using is_at_const_signature = typename std::is_same<decltype(std::declval<const object_type>().at(
2369  std::declval<const string_type>())),
2370  const value_type&>;
2371 
2372 template <typename value_type, typename string_type, typename object_type>
2374 {
2375  static constexpr auto value =
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) &&
2385 
2386  static constexpr auto supports_claims_transform =
2388  std::is_same<typename object_type::value_type,
2389  std::pair<const string_type, value_type>>::value;
2390 };
2391 
2392 template <typename value_type, typename array_type> struct is_valid_json_array
2393 {
2394  static constexpr auto value = std::is_same<typename array_type::value_type, value_type>::value;
2395 };
2396 
2397 template <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>())),
2401  string_type>;
2402 
2403 template <typename string_type, typename integer_type>
2404 using is_substr_start_index_signature = typename std::is_same<
2405  decltype(std::declval<string_type>().substr(std::declval<integer_type>())), string_type>;
2406 
2407 template <typename string_type> struct has_operate_plus_method
2408 { // https://stackoverflow.com/a/9154394/8480874
2409  template <class> struct sfinae_true : std::true_type
2410  {
2411  };
2412 
2413  template <class T, class A0>
2414  static auto test_operator_plus(int)
2415  -> sfinae_true<decltype(std::declval<T>().operator+(std::declval<A0>()))>;
2416  template <class, class A0> static auto test_operator_plus(long) -> std::false_type;
2417 
2418  static constexpr auto value = decltype(test_operator_plus<string_type, string_type>(0)){};
2419 };
2420 
2421 template <typename string_type>
2423  typename std::is_same<decltype(std::operator+(std::declval<string_type>(),
2424  std::declval<string_type>())),
2425  string_type>;
2426 
2427 template <typename string_type, typename integer_type> struct is_valid_json_string
2428 {
2429  static constexpr auto substr =
2432  static_assert(substr,
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");
2435 
2438  static_assert(
2439  operator_plus,
2440  "string_type must have a '+' operator implemented which returns the concatenated string");
2441 
2442  static constexpr auto value = substr && operator_plus;
2443 };
2444 
2445 template <typename value_type, typename string_type, typename integer_type, typename object_type,
2446  typename array_type>
2448 {
2449  // Internal assertions for better feedback
2450  static_assert(
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");
2457 
2458  static constexpr auto value =
2463 };
2464 } // namespace details
2465 
2473 template <typename json_traits> class basic_claim
2474 {
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 "
2485  "std::string.");
2486 
2487  static_assert(details::is_valid_json_types<
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");
2492  static_assert(details::is_valid_traits<json_traits>::value, "traits must satisfy requirements");
2493 
2494  typename json_traits::value_type val;
2495 
2496  public:
2497  using set_t = std::set<typename json_traits::string_type>;
2498 
2499  basic_claim() = default;
2500  basic_claim(const basic_claim&) = default;
2501  basic_claim(basic_claim&&) = default;
2502  basic_claim& operator=(const basic_claim&) = default;
2503  basic_claim& operator=(basic_claim&&) = default;
2504  ~basic_claim() = default;
2505 
2506  JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s) : val(std::move(s)) {}
2508  : val(typename json_traits::integer_type(std::chrono::system_clock::to_time_t(d)))
2509  {
2510  }
2511  JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a) : val(std::move(a)) {}
2512  JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v) : val(std::move(v)) {}
2514  : val(typename json_traits::array_type(s.begin(), s.end()))
2515  {
2516  }
2517  template <typename Iterator>
2518  basic_claim(Iterator begin, Iterator end) : val(typename json_traits::array_type(begin, end))
2519  {
2520  }
2521 
2526  typename json_traits::value_type to_json() const { return val; }
2527 
2532  std::istream& operator>>(std::istream& is) { return is >> val; }
2533 
2538  std::ostream& operator<<(std::ostream& os) { return os << val; }
2539 
2545  json::type get_type() const { return json_traits::get_type(val); }
2546 
2552  typename json_traits::string_type as_string() const { return json_traits::as_string(val); }
2553 
2559  date as_date() const { return std::chrono::system_clock::from_time_t(as_int()); }
2560 
2566  typename json_traits::array_type as_array() const { return json_traits::as_array(val); }
2567 
2573  set_t as_set() const
2574  {
2575  set_t res;
2576  for (const auto& e : json_traits::as_array(val)) { res.insert(json_traits::as_string(e)); }
2577  return res;
2578  }
2579 
2585  typename json_traits::integer_type as_int() const { return json_traits::as_int(val); }
2586 
2592  typename json_traits::boolean_type as_bool() const { return json_traits::as_bool(val); }
2593 
2599  typename json_traits::number_type as_number() const { return json_traits::as_number(val); }
2600 };
2601 
2602 namespace error
2603 {
2607 struct invalid_json_exception : public std::runtime_error
2608 {
2609  invalid_json_exception() : runtime_error("invalid json") {}
2610 };
2614 struct claim_not_present_exception : public std::out_of_range
2615 {
2616  claim_not_present_exception() : out_of_range("claim not found") {}
2617 };
2618 } // namespace error
2619 
2620 namespace details
2621 {
2622 template <typename json_traits> class map_of_claims
2623 {
2624  typename json_traits::object_type claims;
2625 
2626  public:
2628  using iterator = typename json_traits::object_type::iterator;
2629  using const_iterator = typename json_traits::object_type::const_iterator;
2630 
2631  map_of_claims() = default;
2632  map_of_claims(const map_of_claims&) = default;
2633  map_of_claims(map_of_claims&&) = default;
2634  map_of_claims& operator=(const map_of_claims&) = default;
2635  map_of_claims& operator=(map_of_claims&&) = default;
2636 
2637  map_of_claims(typename json_traits::object_type json) : claims(std::move(json)) {}
2638 
2639  iterator begin() { return claims.begin(); }
2640  iterator end() { return claims.end(); }
2641  const_iterator cbegin() const { return claims.begin(); }
2642  const_iterator cend() const { return claims.end(); }
2643  const_iterator begin() const { return claims.begin(); }
2644  const_iterator end() const { return claims.end(); }
2645 
2654  static typename json_traits::object_type
2655  parse_claims(const typename json_traits::string_type& str)
2656  {
2657  typename json_traits::value_type val;
2658  if (!json_traits::parse(val, str))
2660 
2661  return json_traits::as_object(val);
2662  };
2663 
2668  bool has_claim(const typename json_traits::string_type& name) const noexcept
2669  {
2670  return claims.count(name) != 0;
2671  }
2672 
2680  basic_claim_t get_claim(const typename json_traits::string_type& name) const
2681  {
2682  if (!has_claim(name))
2684  return basic_claim_t{claims.at(name)};
2685  }
2686 
2687  std::unordered_map<typename json_traits::string_type, basic_claim_t> get_claims() const
2688  {
2689  static_assert(details::is_valid_json_object<
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`");
2695 
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}); });
2700  return res;
2701  }
2702 };
2703 } // namespace details
2704 
2709 template <typename json_traits> class payload
2710 {
2711  protected:
2713 
2714  public:
2716 
2721  bool has_issuer() const noexcept { return has_payload_claim("iss"); }
2726  bool has_subject() const noexcept { return has_payload_claim("sub"); }
2731  bool has_audience() const noexcept { return has_payload_claim("aud"); }
2736  bool has_expires_at() const noexcept { return has_payload_claim("exp"); }
2741  bool has_not_before() const noexcept { return has_payload_claim("nbf"); }
2746  bool has_issued_at() const noexcept { return has_payload_claim("iat"); }
2751  bool has_id() const noexcept { return has_payload_claim("jti"); }
2758  typename json_traits::string_type get_issuer() const
2759  {
2760  return get_payload_claim("iss").as_string();
2761  }
2768  typename json_traits::string_type get_subject() const
2769  {
2770  return get_payload_claim("sub").as_string();
2771  }
2779  {
2780  auto aud = get_payload_claim("aud");
2781  if (aud.get_type() == json::type::string)
2782  return {aud.as_string()};
2783 
2784  return aud.as_set();
2785  }
2792  date get_expires_at() const { return get_payload_claim("exp").as_date(); }
2799  date get_not_before() const { return get_payload_claim("nbf").as_date(); }
2806  date get_issued_at() const { return get_payload_claim("iat").as_date(); }
2813  typename json_traits::string_type get_id() const
2814  {
2815  return get_payload_claim("jti").as_string();
2816  }
2821  bool has_payload_claim(const typename json_traits::string_type& name) const noexcept
2822  {
2823  return payload_claims.has_claim(name);
2824  }
2830  basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const
2831  {
2832  return payload_claims.get_claim(name);
2833  }
2834 };
2835 
2840 template <typename json_traits> class header
2841 {
2842  protected:
2844 
2845  public:
2851  bool has_algorithm() const noexcept { return has_header_claim("alg"); }
2856  bool has_type() const noexcept { return has_header_claim("typ"); }
2861  bool has_content_type() const noexcept { return has_header_claim("cty"); }
2866  bool has_key_id() const noexcept { return has_header_claim("kid"); }
2873  typename json_traits::string_type get_algorithm() const
2874  {
2875  return get_header_claim("alg").as_string();
2876  }
2883  typename json_traits::string_type get_type() const
2884  {
2885  return get_header_claim("typ").as_string();
2886  }
2893  typename json_traits::string_type get_content_type() const
2894  {
2895  return get_header_claim("cty").as_string();
2896  }
2903  typename json_traits::string_type get_key_id() const
2904  {
2905  return get_header_claim("kid").as_string();
2906  }
2911  bool has_header_claim(const typename json_traits::string_type& name) const noexcept
2912  {
2913  return header_claims.has_claim(name);
2914  }
2920  basic_claim_t get_header_claim(const typename json_traits::string_type& name) const
2921  {
2922  return header_claims.get_claim(name);
2923  }
2924 };
2925 
2929 template <typename json_traits>
2930 class decoded_jwt : public header<json_traits>, public payload<json_traits>
2931 {
2932  protected:
2934  const typename json_traits::string_type token;
2936  typename json_traits::string_type header;
2938  typename json_traits::string_type header_base64;
2940  typename json_traits::string_type payload;
2942  typename json_traits::string_type payload_base64;
2944  typename json_traits::string_type signature;
2946  typename json_traits::string_type signature_base64;
2947 
2948  public:
2950 #ifndef JWT_DISABLE_BASE64
2951 
2960  JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type& token)
2961  : decoded_jwt(
2962  token, [](const typename json_traits::string_type& str)
2963  { return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(str)); })
2964  {
2965  }
2966 #endif
2967 
2978  template <typename Decode>
2979  decoded_jwt(const typename json_traits::string_type& token, Decode decode) : token(token)
2980  {
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);
2990 
2991  header = decode(header_base64);
2992  payload = decode(payload_base64);
2993  signature = decode(signature_base64);
2994 
2997  }
2998 
3003  const typename json_traits::string_type& get_token() const noexcept { return token; }
3008  const typename json_traits::string_type& get_header() const noexcept { return header; }
3013  const typename json_traits::string_type& get_payload() const noexcept { return payload; }
3018  const typename json_traits::string_type& get_signature() const noexcept { return signature; }
3023  const typename json_traits::string_type& get_header_base64() const noexcept
3024  {
3025  return header_base64;
3026  }
3031  const typename json_traits::string_type& get_payload_base64() const noexcept
3032  {
3033  return payload_base64;
3034  }
3039  const typename json_traits::string_type& get_signature_base64() const noexcept
3040  {
3041  return signature_base64;
3042  }
3047  std::unordered_map<typename json_traits::string_type, basic_claim_t> get_payload_claims() const
3048  {
3049  return this->payload_claims.get_claims();
3050  }
3055  std::unordered_map<typename json_traits::string_type, basic_claim_t> get_header_claims() const
3056  {
3057  return this->header_claims.get_claims();
3058  }
3066  basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const
3067  {
3068  return this->payload_claims.get_claim(name);
3069  }
3077  basic_claim_t get_header_claim(const typename json_traits::string_type& name) const
3078  {
3079  return this->header_claims.get_claim(name);
3080  }
3081 };
3082 
3087 template <typename json_traits> class builder
3088 {
3089  typename json_traits::object_type header_claims;
3090  typename json_traits::object_type payload_claims;
3091 
3092  public:
3093  builder() = default;
3100  builder& set_header_claim(const typename json_traits::string_type& id,
3101  typename json_traits::value_type c)
3102  {
3103  header_claims[id] = std::move(c);
3104  return *this;
3105  }
3106 
3113  builder& set_header_claim(const typename json_traits::string_type& id,
3115  {
3116  header_claims[id] = c.to_json();
3117  return *this;
3118  }
3125  builder& set_payload_claim(const typename json_traits::string_type& id,
3126  typename json_traits::value_type c)
3127  {
3128  payload_claims[id] = std::move(c);
3129  return *this;
3130  }
3137  builder& set_payload_claim(const typename json_traits::string_type& id,
3139  {
3140  payload_claims[id] = c.to_json();
3141  return *this;
3142  }
3150  builder& set_algorithm(typename json_traits::string_type str)
3151  {
3152  return set_header_claim("alg", typename json_traits::value_type(str));
3153  }
3159  builder& set_type(typename json_traits::string_type str)
3160  {
3161  return set_header_claim("typ", typename json_traits::value_type(str));
3162  }
3168  builder& set_content_type(typename json_traits::string_type str)
3169  {
3170  return set_header_claim("cty", typename json_traits::value_type(str));
3171  }
3178  builder& set_key_id(typename json_traits::string_type str)
3179  {
3180  return set_header_claim("kid", typename json_traits::value_type(str));
3181  }
3187  builder& set_issuer(typename json_traits::string_type str)
3188  {
3189  return set_payload_claim("iss", typename json_traits::value_type(str));
3190  }
3196  builder& set_subject(typename json_traits::string_type str)
3197  {
3198  return set_payload_claim("sub", typename json_traits::value_type(str));
3199  }
3205  builder& set_audience(typename json_traits::array_type a)
3206  {
3207  return set_payload_claim("aud", typename json_traits::value_type(a));
3208  }
3214  builder& set_audience(typename json_traits::string_type aud)
3215  {
3216  return set_payload_claim("aud", typename json_traits::value_type(aud));
3217  }
3224  {
3225  return set_payload_claim("exp", basic_claim<json_traits>(d));
3226  }
3233  {
3234  return set_payload_claim("nbf", basic_claim<json_traits>(d));
3235  }
3242  {
3243  return set_payload_claim("iat", basic_claim<json_traits>(d));
3244  }
3250  builder& set_id(const typename json_traits::string_type& str)
3251  {
3252  return set_payload_claim("jti", typename json_traits::value_type(str));
3253  }
3254 
3266  template <typename Algo, typename Encode>
3267  typename json_traits::string_type sign(const Algo& algo, Encode encode) const
3268  {
3269  std::error_code ec;
3270  auto res = sign(algo, encode, ec);
3272  return res;
3273  }
3274 #ifndef JWT_DISABLE_BASE64
3275 
3283  template <typename Algo> typename json_traits::string_type sign(const Algo& algo) const
3284  {
3285  std::error_code ec;
3286  auto res = sign(algo, ec);
3288  return res;
3289  }
3290 #endif
3291 
3304  template <typename Algo, typename Encode>
3305  typename json_traits::string_type sign(const Algo& algo, Encode encode,
3306  std::error_code& ec) const
3307  {
3308  // make a copy such that a builder can be re-used
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());
3312 
3313  const auto header =
3314  encode(json_traits::serialize(typename json_traits::value_type(obj_header)));
3315  const auto payload =
3316  encode(json_traits::serialize(typename json_traits::value_type(payload_claims)));
3317  const auto token = header + "." + payload;
3318 
3319  auto signature = algo.sign(token, ec);
3320  if (ec)
3321  return {};
3322 
3323  return token + "." + encode(signature);
3324  }
3325 #ifndef JWT_DISABLE_BASE64
3326 
3335  template <typename Algo>
3336  typename json_traits::string_type sign(const Algo& algo, std::error_code& ec) const
3337  {
3338  return sign(
3339  algo,
3340  [](const typename json_traits::string_type& data)
3341  { return base::trim<alphabet::base64url>(base::encode<alphabet::base64url>(data)); },
3342  ec);
3343  }
3344 #endif
3345 };
3346 
3347 namespace verify_ops
3348 {
3352 template <typename json_traits> struct verify_context
3353 {
3354  verify_context(date ctime, const decoded_jwt<json_traits>& j, size_t l)
3355  : current_time(ctime), jwt(j), default_leeway(l)
3356  {
3357  }
3358  // Current time, retrieved from the verifiers clock and cached for performance and consistency
3360  // The jwt passed to the verifier
3362  // The configured default leeway for this verification
3363  size_t default_leeway{0};
3364 
3365  // The claim key to apply this comparision on
3366  typename json_traits::string_type claim_key{};
3367 
3368  // Helper method to get a claim from the jwt in this context
3369  basic_claim<json_traits> get_claim(bool in_header, std::error_code& ec) const
3370  {
3371  if (in_header)
3372  {
3373  if (!jwt.has_header_claim(claim_key))
3374  {
3375  ec = error::token_verification_error::missing_claim;
3376  return {};
3377  }
3378  return jwt.get_header_claim(claim_key);
3379  }
3380  else
3381  {
3382  if (!jwt.has_payload_claim(claim_key))
3383  {
3384  ec = error::token_verification_error::missing_claim;
3385  return {};
3386  }
3387  return jwt.get_payload_claim(claim_key);
3388  }
3389  }
3390  basic_claim<json_traits> get_claim(bool in_header, json::type t, std::error_code& ec) const
3391  {
3392  auto c = get_claim(in_header, ec);
3393  if (ec)
3394  return {};
3395  if (c.get_type() != t)
3396  {
3397  ec = error::token_verification_error::claim_type_missmatch;
3398  return {};
3399  }
3400  return c;
3401  }
3402  basic_claim<json_traits> get_claim(std::error_code& ec) const { return get_claim(false, ec); }
3403  basic_claim<json_traits> get_claim(json::type t, std::error_code& ec) const
3404  {
3405  return get_claim(false, t, ec);
3406  }
3407 };
3408 
3412 template <typename json_traits, bool in_header = false> struct equals_claim
3413 {
3415  void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const
3416  {
3417  auto jc = ctx.get_claim(in_header, expected.get_type(), ec);
3418  if (ec)
3419  return;
3420  const bool matches = [&]()
3421  {
3422  switch (expected.get_type())
3423  {
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");
3433  }
3434  }();
3435  if (!matches)
3436  {
3437  ec = error::token_verification_error::claim_value_missmatch;
3438  return;
3439  }
3440  }
3441 };
3442 
3447 template <typename json_traits, bool in_header = false> struct date_before_claim
3448 {
3449  const size_t leeway;
3450  void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const
3451  {
3452  auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3453  if (ec)
3454  return;
3455  auto c = jc.as_date();
3456  if (ctx.current_time > c + std::chrono::seconds(leeway))
3457  {
3458  ec = error::token_verification_error::token_expired;
3459  }
3460  }
3461 };
3462 
3467 template <typename json_traits, bool in_header = false> struct date_after_claim
3468 {
3469  const size_t leeway;
3470  void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const
3471  {
3472  auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3473  if (ec)
3474  return;
3475  auto c = jc.as_date();
3476  if (ctx.current_time < c - std::chrono::seconds(leeway))
3477  {
3478  ec = error::token_verification_error::token_expired;
3479  }
3480  }
3481 };
3482 
3488 template <typename json_traits, bool in_header = false> struct is_subset_claim
3489 {
3491  void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const
3492  {
3493  auto c = ctx.get_claim(in_header, ec);
3494  if (ec)
3495  return;
3496  if (c.get_type() == json::type::string)
3497  {
3498  if (expected.size() != 1 || *expected.begin() != c.as_string())
3499  {
3500  ec = error::token_verification_error::audience_missmatch;
3501  return;
3502  }
3503  }
3504  else if (c.get_type() == json::type::array)
3505  {
3506  auto jc = c.as_set();
3507  for (auto& e : expected)
3508  {
3509  if (jc.find(e) == jc.end())
3510  {
3511  ec = error::token_verification_error::audience_missmatch;
3512  return;
3513  }
3514  }
3515  }
3516  else
3517  {
3518  ec = error::token_verification_error::claim_type_missmatch;
3519  return;
3520  }
3521  }
3522 };
3523 
3527 template <typename json_traits, bool in_header = false> struct insensitive_string_claim
3528 {
3529  const typename json_traits::string_type expected;
3530  std::locale locale;
3531  insensitive_string_claim(const typename json_traits::string_type& e, std::locale loc)
3532  : expected(to_lower_unicode(e, loc)), locale(loc)
3533  {
3534  }
3535 
3536  void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const
3537  {
3538  const auto c = ctx.get_claim(in_header, json::type::string, ec);
3539  if (ec)
3540  return;
3541  if (to_lower_unicode(c.as_string(), locale) != expected)
3542  {
3543  ec = error::token_verification_error::claim_value_missmatch;
3544  }
3545  }
3546 
3547  static std::string to_lower_unicode(const std::string& str, const std::locale& loc)
3548  {
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);
3554  }
3555 };
3556 } // namespace verify_ops
3557 
3562 template <typename Clock, typename json_traits> class verifier
3563 {
3564  public:
3575  using verify_check_fn_t =
3576  std::function<void(const verify_ops::verify_context<json_traits>&, std::error_code& ec)>;
3577 
3578  private:
3579  struct algo_base
3580  {
3581  virtual ~algo_base() = default;
3582  virtual void verify(const std::string& data, const std::string& sig,
3583  std::error_code& ec) = 0;
3584  };
3585  template <typename T> struct algo : public algo_base
3586  {
3587  T alg;
3588  explicit algo(T a) : alg(a) {}
3589  void verify(const std::string& data, const std::string& sig, std::error_code& ec) override
3590  {
3591  alg.verify(data, sig, ec);
3592  }
3593  };
3595  std::unordered_map<typename json_traits::string_type, verify_check_fn_t> claims;
3597  size_t default_leeway = 0;
3599  Clock clock;
3601  std::unordered_map<std::string, std::shared_ptr<algo_base>> algs;
3602 
3603  public:
3608  explicit verifier(Clock c) : clock(c)
3609  {
3610  claims["exp"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec)
3611  {
3612  if (!ctx.jwt.has_expires_at())
3613  return;
3614  auto exp = ctx.jwt.get_expires_at();
3615  if (ctx.current_time > exp + std::chrono::seconds(ctx.default_leeway))
3616  {
3617  ec = error::token_verification_error::token_expired;
3618  }
3619  };
3620  claims["iat"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec)
3621  {
3622  if (!ctx.jwt.has_issued_at())
3623  return;
3624  auto iat = ctx.jwt.get_issued_at();
3625  if (ctx.current_time < iat - std::chrono::seconds(ctx.default_leeway))
3626  {
3627  ec = error::token_verification_error::token_expired;
3628  }
3629  };
3630  claims["nbf"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec)
3631  {
3632  if (!ctx.jwt.has_not_before())
3633  return;
3634  auto nbf = ctx.jwt.get_not_before();
3635  if (ctx.current_time < nbf - std::chrono::seconds(ctx.default_leeway))
3636  {
3637  ec = error::token_verification_error::token_expired;
3638  }
3639  };
3640  }
3641 
3647  verifier& leeway(size_t leeway)
3648  {
3649  default_leeway = leeway;
3650  return *this;
3651  }
3658  verifier& expires_at_leeway(size_t leeway)
3659  {
3660  claims["exp"] = verify_ops::date_before_claim<json_traits>{leeway};
3661  return *this;
3662  }
3669  verifier& not_before_leeway(size_t leeway)
3670  {
3671  claims["nbf"] = verify_ops::date_after_claim<json_traits>{leeway};
3672  return *this;
3673  }
3680  verifier& issued_at_leeway(size_t leeway)
3681  {
3682  claims["iat"] = verify_ops::date_after_claim<json_traits>{leeway};
3683  return *this;
3684  }
3685 
3697  verifier& with_type(const typename json_traits::string_type& type,
3698  std::locale locale = std::locale{})
3699  {
3701  type, std::move(locale)});
3702  }
3703 
3710  verifier& with_issuer(const typename json_traits::string_type& iss)
3711  {
3712  return with_claim("iss", basic_claim_t(iss));
3713  }
3714 
3721  verifier& with_subject(const typename json_traits::string_type& sub)
3722  {
3723  return with_claim("sub", basic_claim_t(sub));
3724  }
3732  {
3733  claims["aud"] = verify_ops::is_subset_claim<json_traits>{aud};
3734  return *this;
3735  }
3742  verifier& with_audience(const typename json_traits::string_type& aud)
3743  {
3744  typename basic_claim_t::set_t s;
3745  s.insert(aud);
3746  return with_audience(s);
3747  }
3754  verifier& with_id(const typename json_traits::string_type& id)
3755  {
3756  return with_claim("jti", basic_claim_t(id));
3757  }
3758 
3765  verifier& with_claim(const typename json_traits::string_type& name, verify_check_fn_t fn)
3766  {
3767  claims[name] = fn;
3768  return *this;
3769  }
3770 
3777  verifier& with_claim(const typename json_traits::string_type& name, basic_claim_t c)
3778  {
3779  return with_claim(name, verify_ops::equals_claim<json_traits>{c});
3780  }
3781 
3787  template <typename Algorithm> verifier& allow_algorithm(Algorithm alg)
3788  {
3789  algs[alg.name()] = std::make_shared<algo<Algorithm>>(alg);
3790  return *this;
3791  }
3792 
3799  {
3800  std::error_code ec;
3801  verify(jwt, ec);
3803  }
3809  void verify(const decoded_jwt<json_traits>& jwt, std::error_code& ec) const
3810  {
3811  ec.clear();
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)
3817  {
3818  ec = error::token_verification_error::wrong_algorithm;
3819  return;
3820  }
3821  algs.at(algo)->verify(data, sig, ec);
3822  if (ec)
3823  return;
3824 
3825  verify_ops::verify_context<json_traits> ctx{clock.now(), jwt, default_leeway};
3826  for (auto& c : claims)
3827  {
3828  ctx.claim_key = c.first;
3829  c.second(ctx, ec);
3830  if (ec)
3831  return;
3832  }
3833  }
3834 };
3835 
3844 template <typename json_traits> class jwk
3845 {
3847  const details::map_of_claims<json_traits> jwk_claims;
3848 
3849  public:
3850  JWT_CLAIM_EXPLICIT jwk(const typename json_traits::string_type& str)
3851  : jwk_claims(details::map_of_claims<json_traits>::parse_claims(str))
3852  {
3853  }
3854 
3855  JWT_CLAIM_EXPLICIT jwk(const typename json_traits::value_type& json)
3856  : jwk_claims(json_traits::as_object(json))
3857  {
3858  }
3859 
3868  typename json_traits::string_type get_key_type() const
3869  {
3870  return get_jwk_claim("kty").as_string();
3871  }
3872 
3879  typename json_traits::string_type get_use() const { return get_jwk_claim("use").as_string(); }
3880 
3888  {
3889  return get_jwk_claim("key_ops").as_set();
3890  }
3891 
3898  typename json_traits::string_type get_algorithm() const
3899  {
3900  return get_jwk_claim("alg").as_string();
3901  }
3902 
3909  typename json_traits::string_type get_key_id() const
3910  {
3911  return get_jwk_claim("kid").as_string();
3912  }
3913 
3924  typename json_traits::string_type get_curve() const { return get_jwk_claim("crv").as_string(); }
3925 
3932  typename json_traits::array_type get_x5c() const { return get_jwk_claim("x5c").as_array(); };
3933 
3940  typename json_traits::string_type get_x5u() const { return get_jwk_claim("x5u").as_string(); };
3941 
3948  typename json_traits::string_type get_x5t() const { return get_jwk_claim("x5t").as_string(); };
3949 
3956  typename json_traits::string_type get_x5t_sha256() const
3957  {
3958  return get_jwk_claim("x5t#S256").as_string();
3959  };
3960 
3967  typename json_traits::string_type get_x5c_key_value() const
3968  {
3969  auto x5c_array = get_jwk_claim("x5c").as_array();
3970  if (x5c_array.size() == 0)
3972 
3973  return json_traits::as_string(x5c_array.front());
3974  };
3975 
3980  bool has_key_type() const noexcept { return has_jwk_claim("kty"); }
3981 
3986  bool has_use() const noexcept { return has_jwk_claim("use"); }
3987 
3992  bool has_key_operations() const noexcept { return has_jwk_claim("key_ops"); }
3993 
3998  bool has_algorithm() const noexcept { return has_jwk_claim("alg"); }
3999 
4004  bool has_curve() const noexcept { return has_jwk_claim("crv"); }
4005 
4010  bool has_key_id() const noexcept { return has_jwk_claim("kid"); }
4011 
4016  bool has_x5u() const noexcept { return has_jwk_claim("x5u"); }
4017 
4022  bool has_x5c() const noexcept { return has_jwk_claim("x5c"); }
4023 
4028  bool has_x5t() const noexcept { return has_jwk_claim("x5t"); }
4029 
4034  bool has_x5t_sha256() const noexcept { return has_jwk_claim("x5t#S256"); }
4035 
4040  bool has_jwk_claim(const typename json_traits::string_type& name) const noexcept
4041  {
4042  return jwk_claims.has_claim(name);
4043  }
4044 
4050  basic_claim_t get_jwk_claim(const typename json_traits::string_type& name) const
4051  {
4052  return jwk_claims.get_claim(name);
4053  }
4054 
4055  bool empty() const noexcept { return jwk_claims.empty(); }
4056 };
4057 
4068 template <typename json_traits> class jwks
4069 {
4070  public:
4072  using jwt_vector_t = std::vector<jwk_t>;
4073  using iterator = typename jwt_vector_t::iterator;
4074  using const_iterator = typename jwt_vector_t::const_iterator;
4075 
4076  JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type& str)
4077  {
4078  typename json_traits::value_type parsed_val;
4079  if (!json_traits::parse(parsed_val, str))
4081 
4082  const details::map_of_claims<json_traits> jwks_json = json_traits::as_object(parsed_val);
4083  if (!jwks_json.has_claim("keys"))
4085 
4086  auto jwk_list = jwks_json.get_claim("keys").as_array();
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}; });
4089  }
4090 
4091  iterator begin() { return jwk_claims.begin(); }
4092  iterator end() { return jwk_claims.end(); }
4093  const_iterator cbegin() const { return jwk_claims.begin(); }
4094  const_iterator cend() const { return jwk_claims.end(); }
4095  const_iterator begin() const { return jwk_claims.begin(); }
4096  const_iterator end() const { return jwk_claims.end(); }
4097 
4102  bool has_jwk(const typename json_traits::string_type& key_id) const noexcept
4103  {
4104  return find_by_kid(key_id) != end();
4105  }
4106 
4112  jwk_t get_jwk(const typename json_traits::string_type& key_id) const
4113  {
4114  const auto maybe = find_by_kid(key_id);
4115  if (maybe == end())
4117  return *maybe;
4118  }
4119 
4120  private:
4121  jwt_vector_t jwk_claims;
4122 
4123  const_iterator find_by_kid(const typename json_traits::string_type& key_id) const noexcept
4124  {
4125  return std::find_if(cbegin(), cend(),
4126  [key_id](const jwk_t& jwk)
4127  {
4128  if (!jwk.has_key_id())
4129  {
4130  return false;
4131  }
4132  return jwk.get_key_id() == key_id;
4133  });
4134  }
4135 };
4136 
4142 template <typename Clock, typename json_traits> verifier<Clock, json_traits> verify(Clock c)
4143 {
4144  return verifier<Clock, json_traits>(c);
4145 }
4146 
4151 {
4152  date now() const { return date::clock::now(); }
4153 };
4154 
4160 template <typename json_traits> verifier<default_clock, json_traits> verify(default_clock c = {})
4161 {
4162  return verifier<default_clock, json_traits>(c);
4163 }
4164 
4168 template <typename json_traits> builder<json_traits> create() { return builder<json_traits>(); }
4169 
4178 template <typename json_traits, typename Decode>
4179 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token, Decode decode)
4180 {
4181  return decoded_jwt<json_traits>(token, decode);
4182 }
4183 
4191 template <typename json_traits>
4192 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token)
4193 {
4194  return decoded_jwt<json_traits>(token);
4195 }
4196 
4197 template <typename json_traits>
4198 jwk<json_traits> parse_jwk(const typename json_traits::string_type& token)
4199 {
4200  return jwk<json_traits>(token);
4201 }
4202 
4203 template <typename json_traits>
4204 jwks<json_traits> parse_jwks(const typename json_traits::string_type& token)
4205 {
4206  return jwks<json_traits>(token);
4207 }
4208 } // namespace jwt
4209 
4210 template <typename json_traits>
4211 std::istream& operator>>(std::istream& is, jwt::basic_claim<json_traits>& c)
4212 {
4213  return c.operator>>(is);
4214 }
4215 
4216 template <typename json_traits>
4217 std::ostream& operator<<(std::ostream& os, const jwt::basic_claim<json_traits>& c)
4218 {
4219  return os << c.to_json();
4220 }
4221 
4222 #ifndef JWT_DISABLE_PICOJSON
4223 #include "traits/kazuho-picojson/defaults.h"
4224 #endif
4225 
4226 #endif
jwt::details::is_end_const_signature
typename std::is_same< decltype(std::declval< const object_type >().end()), has_const_iterator< object_type > > is_end_const_signature
Definition: jwt.h:2327
jwt::details::nonesuch::operator=
void operator=(nonesuch const &)=delete
jwt::error::make_error_code
std::error_code make_error_code(rsa_error e)
Definition: jwt.h:154
jwt::payload::has_expires_at
bool has_expires_at() const noexcept
Definition: jwt.h:2736
jwt::error::rsa_error::load_key_bio_read
@ load_key_bio_read
jwt::basic_claim::~basic_claim
~basic_claim()=default
jwt::builder::set_header_claim
builder & set_header_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition: jwt.h:3113
jwt::details::has_operate_plus_method
Definition: jwt.h:2407
jwt::details::map_of_claims::iterator
typename json_traits::object_type::iterator iterator
Definition: jwt.h:2628
jwt::jwks::cend
const_iterator cend() const
Definition: jwt.h:4094
jwt::payload::get_expires_at
date get_expires_at() const
Definition: jwt.h:2792
jwt::details::map_of_claims
Definition: jwt.h:2622
jwt::jwk::get_x5t_sha256
json_traits::string_type get_x5t_sha256() const
Definition: jwt.h:3956
jwt::algorithm::hmacsha::sign
std::string sign(const std::string &data, std::error_code &ec) const
Definition: jwt.h:965
jwt::helper::load_public_key_from_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.
Definition: jwt.h:629
jwt::verify_ops::date_after_claim
Definition: jwt.h:3467
jwt::verify_ops::insensitive_string_claim::expected
const json_traits::string_type expected
Definition: jwt.h:3529
jwt::decoded_jwt::get_token
const json_traits::string_type & get_token() const noexcept
Definition: jwt.h:3003
jwt::details::is_at_const_signature
typename std::is_same< decltype(std::declval< const object_type >().at(std::declval< const string_type >())), const value_type & > is_at_const_signature
Definition: jwt.h:2370
jwt::algorithm::rs256
Definition: jwt.h:1800
jwt::details::is_end_signature
typename std::is_same< decltype(std::declval< object_type >().end()), has_iterator< object_type > > is_end_signature
Definition: jwt.h:2322
jwt::error::signature_generation_error::signature_decoding_failed
@ signature_decoding_failed
jwt::algorithm::es384
Definition: jwt.h:1882
jwt::error::signature_generation_error::set_rsa_pss_saltlen_failed
@ set_rsa_pss_saltlen_failed
jwt::jwk::jwk
JWT_CLAIM_EXPLICIT jwk(const typename json_traits::string_type &str)
Definition: jwt.h:3850
jwt::algorithm::rsa::rsa
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)
Definition: jwt.h:1035
jwt::verify
verifier< default_clock, json_traits > verify(default_clock c={})
Definition: jwt.h:4160
goby::ev
extern ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::EnumValueOptions, ::google::protobuf::internal::MessageTypeTraits< ::goby::GobyEnumValueOptions >, 11, false > ev
Definition: option_extensions.pb.h:1331
jwt::algorithm::eddsa::name
std::string name() const
Definition: jwt.h:1592
jwt::verifier::not_before_leeway
verifier & not_before_leeway(size_t leeway)
Definition: jwt.h:3669
jwt::details::detector< Default, void_t< Op< Args... > >, Op, Args... >::value
std::true_type value
Definition: jwt.h:2124
jwt::header::has_algorithm
bool has_algorithm() const noexcept
Definition: jwt.h:2851
jwt::verifier::with_type
verifier & with_type(const typename json_traits::string_type &type, std::locale locale=std::locale{})
Definition: jwt.h:3697
jwt::basic_claim::basic_claim
JWT_CLAIM_EXPLICIT basic_claim(const set_t &s)
Definition: jwt.h:2513
jwt::algorithm::pss::pss
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)
Definition: jwt.h:1615
jwt::error::rsa_error::ok
@ ok
jwt::builder::set_algorithm
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 ...
Definition: jwt.h:3150
jwt::builder::set_issued_at
builder & set_issued_at(const date &d)
Definition: jwt.h:3241
jwt::error::rsa_error::write_cert_failed
@ write_cert_failed
jwt::error::signature_generation_error::hmac_failed
@ hmac_failed
jwt::jwk::has_curve
bool has_curve() const noexcept
Definition: jwt.h:4004
jwt::helper::extract_pubkey_from_cert
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.
Definition: jwt.h:451
jwt::basic_claim::basic_claim
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s)
Definition: jwt.h:2506
jwt::algorithm::ps384::ps384
ps384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:2031
jwt::algorithm::none::name
std::string name() const
Get algorithm name.
Definition: jwt.h:942
jwt::payload::get_payload_claim
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:2830
jwt::verify_ops::insensitive_string_claim
Definition: jwt.h:3527
jwt::verifier::with_claim
verifier & with_claim(const typename json_traits::string_type &name, verify_check_fn_t fn)
Definition: jwt.h:3765
jwt::error::ecdsa_error::load_key_bio_write
@ load_key_bio_write
jwt::helper::convert_base64_der_to_pem
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.
Definition: jwt.h:530
jwt::details::is_as_number_signature
typename std::is_same< as_number_function< traits_type >, number_type(const value_type &)> is_as_number_signature
Definition: jwt.h:2196
jwt::details::is_valid_json_array
Definition: jwt.h:2392
jwt::basic_claim::set_t
std::set< typename json_traits::string_type > set_t
Definition: jwt.h:2497
jwt::algorithm::pss::verify
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition: jwt.h:1700
jwt::error::ecdsa_error::create_mem_bio_failed
@ create_mem_bio_failed
jwt::details::has_subcription_operator
Definition: jwt.h:2342
jwt::details::has_subcription_operator::sfinae_true
Definition: jwt.h:2344
jwt::details::map_of_claims::parse_claims
static json_traits::object_type parse_claims(const typename json_traits::string_type &str)
Parse a JSON string into a map of claims.
Definition: jwt.h:2655
jwt::algorithm::ecdsa::name
std::string name() const
Definition: jwt.h:1303
jwt::header::get_key_id
json_traits::string_type get_key_id() const
Definition: jwt.h:2903
jwt::payload::has_issued_at
bool has_issued_at() const noexcept
Definition: jwt.h:2746
jwt::jwks::end
const_iterator end() const
Definition: jwt.h:4096
jwt::payload::has_id
bool has_id() const noexcept
Definition: jwt.h:2751
jwt::verify_ops::equals_claim::operator()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
Definition: jwt.h:3415
jwt::json::type::integer
@ integer
jwt::builder::set_subject
builder & set_subject(typename json_traits::string_type str)
Definition: jwt.h:3196
jwt::details::is_valid_json_object::supports_claims_transform
static constexpr auto supports_claims_transform
Definition: jwt.h:2386
jwt::details::make_void::type
void type
Definition: jwt.h:2090
jwt::details::has_const_iterator
typename object_type::const_iterator has_const_iterator
Definition: jwt.h:2301
jwt::decoded_jwt::signature_base64
json_traits::string_type signature_base64
Unmodified signature part in base64.
Definition: jwt.h:2946
jwt::helper::raw2bn
std::unique_ptr< BIGNUM, decltype(&BN_free)> raw2bn(const std::string &raw)
Definition: jwt.h:890
jwt::builder::set_payload_claim
builder & set_payload_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition: jwt.h:3125
jwt::json::type::string
@ string
jwt::error::token_verification_error
token_verification_error
Errors related to token verification errors.
Definition: jwt.h:342
jwt::verifier::allow_algorithm
verifier & allow_algorithm(Algorithm alg)
Definition: jwt.h:3787
jwt::error::signature_verification_error_category
std::error_category & signature_verification_error_category()
Error category for verification errors.
Definition: jwt.h:225
jwt::error::ecdsa_error::load_key_bio_read
@ load_key_bio_read
jwt::verifier
Definition: jwt.h:3562
jwt::builder::set_content_type
builder & set_content_type(typename json_traits::string_type str)
Definition: jwt.h:3168
jwt::algorithm::rs384
Definition: jwt.h:1820
jwt::jwk::has_use
bool has_use() const noexcept
Definition: jwt.h:3986
jwt::jwk::has_x5t_sha256
bool has_x5t_sha256() const noexcept
Definition: jwt.h:4034
jwt::basic_claim::operator<<
std::ostream & operator<<(std::ostream &os)
Definition: jwt.h:2538
jwt::payload::has_payload_claim
bool has_payload_claim(const typename json_traits::string_type &name) const noexcept
Definition: jwt.h:2821
jwt::details::as_integer_function
decltype(traits_type::as_int) as_integer_function
Definition: jwt.h:2208
jwt::algorithm::none::verify
void verify(const std::string &, const std::string &signature, std::error_code &ec) const
Check if the given signature is empty.
Definition: jwt.h:932
jwt::algorithm::hmacsha
Base class for HMAC family of algorithms.
Definition: jwt.h:947
jwt::details::as_boolean_function
decltype(traits_type::as_bool) as_boolean_function
Definition: jwt.h:2225
jwt::error::signature_generation_error::digestfinal_failed
@ digestfinal_failed
operator<<
std::ostream & operator<<(std::ostream &os, const jwt::basic_claim< json_traits > &c)
Definition: jwt.h:4217
jwt::jwk::has_x5t
bool has_x5t() const noexcept
Definition: jwt.h:4028
jwt::decoded_jwt::decoded_jwt
decoded_jwt(const typename json_traits::string_type &token, Decode decode)
Parses a given token.
Definition: jwt.h:2979
jwt::error::token_verification_error::claim_value_missmatch
@ claim_value_missmatch
jwt::verifier::with_subject
verifier & with_subject(const typename json_traits::string_type &sub)
Definition: jwt.h:3721
jwt::verifier::with_id
verifier & with_id(const typename json_traits::string_type &id)
Definition: jwt.h:3754
jwt::details::is_subcription_operator_signature::has_subscription_operator
static constexpr auto has_subscription_operator
Definition: jwt.h:2359
jwt::details::supports_as_object::value
static constexpr auto value
Definition: jwt.h:2156
jwt::details::is_valid_json_string::operator_plus
static constexpr auto operator_plus
Definition: jwt.h:2436
jwt::builder::set_payload_claim
builder & set_payload_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition: jwt.h:3137
goby::util::e
constexpr T e
Definition: constants.h:35
jwt::header::get_type
json_traits::string_type get_type() const
Definition: jwt.h:2883
basic_json::type
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:20459
jwt::algorithm::ps256
Definition: jwt.h:2002
jwt::error::signature_generation_error_category
std::error_category & signature_generation_error_category()
Error category for signature generation errors.
Definition: jwt.h:288
jwt::details::is_valid_json_types
Definition: jwt.h:2447
jwt::verify_ops::is_subset_claim
Definition: jwt.h:3488
jwt::jwk::get_x5t
json_traits::string_type get_x5t() const
Definition: jwt.h:3948
jwt::error::ecdsa_error_category
std::error_category & ecdsa_error_category()
Error category for ECDSA errors.
Definition: jwt.h:175
jwt::verify_ops::insensitive_string_claim::locale
std::locale locale
Definition: jwt.h:3530
jwt::error::rsa_error::load_key_bio_write
@ load_key_bio_write
jwt::error::ecdsa_error::invalid_key
@ invalid_key
basic_json
namespace for Niels Lohmann
Definition: json.hpp:3393
jwt::builder::set_key_id
builder & set_key_id(typename json_traits::string_type str)
Set key id claim.
Definition: jwt.h:3178
jwt::algorithm::es512
Definition: jwt.h:1904
jwt::details::map_of_claims::const_iterator
typename json_traits::object_type::const_iterator const_iterator
Definition: jwt.h:2629
jwt::builder::set_id
builder & set_id(const typename json_traits::string_type &str)
Definition: jwt.h:3250
jwt::error::signature_verification_error::get_key_failed
@ get_key_failed
jwt::jwks::end
iterator end()
Definition: jwt.h:4092
base.h
jwt::algorithm::rs512::rs512
rs512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1849
jwt::details::supports_get_type
Definition: jwt.h:2141
jwt::header::has_key_id
bool has_key_id() const noexcept
Definition: jwt.h:2866
jwt::decoded_jwt::payload
json_traits::string_type payload
Payload part decoded from base64.
Definition: jwt.h:2940
jwt::verify_ops::verify_context::jwt
const decoded_jwt< json_traits > & jwt
Definition: jwt.h:3361
jwt::error::rsa_error::convert_to_pem_failed
@ convert_to_pem_failed
goby::time::str
std::string str(TimeType value=SystemClock::now< TimeType >())
Returns the provided time (or current time if omitted) as a human-readable string.
Definition: convert.h:191
jwt::decoded_jwt
Definition: jwt.h:2930
jwt::verifier::verifier
verifier(Clock c)
Definition: jwt.h:3608
jwt::error::rsa_exception
Definition: jwt.h:94
jwt::decoded_jwt::signature
json_traits::string_type signature
Signature part decoded from base64.
Definition: jwt.h:2944
jwt::helper::load_private_key_from_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.
Definition: jwt.h:700
jwt::error::ecdsa_error::invalid_key_size
@ invalid_key_size
jwt::verifier::with_issuer
verifier & with_issuer(const typename json_traits::string_type &iss)
Definition: jwt.h:3710
jwt::details::map_of_claims::get_claim
basic_claim_t get_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:2680
jwt::algorithm::pss::name
std::string name() const
Definition: jwt.h:1753
jwt::jwk
JSON Web Key.
Definition: jwt.h:3844
jwt::details::is_as_integer_signature
typename std::is_same< as_integer_function< traits_type >, integer_type(const value_type &)> is_as_integer_signature
Definition: jwt.h:2212
jwt::basic_claim::as_date
date as_date() const
Definition: jwt.h:2559
jwt::error::ecdsa_error::ok
@ ok
jwt::jwks::jwks
JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type &str)
Definition: jwt.h:4076
jwt::algorithm::ecdsa::sign
std::string sign(const std::string &data, std::error_code &ec) const
Definition: jwt.h:1198
jwt::verifier::verify_check_fn_t
std::function< void(const verify_ops::verify_context< json_traits > &, std::error_code &ec)> verify_check_fn_t
Definition: jwt.h:3576
jwt::details::is_get_type_signature
typename std::is_same< get_type_function< traits_type >, json::type(const value_type &)> is_get_type_signature
Definition: jwt.h:2139
jwt::error::signature_verification_error::signature_encoding_failed
@ signature_encoding_failed
jwt::details::is_count_signature
typename std::is_integral< decltype(std::declval< const object_type >().count(std::declval< const string_type >()))> is_count_signature
Definition: jwt.h:2340
jwt::decoded_jwt::get_header
const json_traits::string_type & get_header() const noexcept
Definition: jwt.h:3008
jwt::details::is_valid_json_array::value
static constexpr auto value
Definition: jwt.h:2394
jwt::builder::sign
json_traits::string_type sign(const Algo &algo, Encode encode) const
Definition: jwt.h:3267
jwt::header::has_type
bool has_type() const noexcept
Definition: jwt.h:2856
jwt::details::map_of_claims::end
const_iterator end() const
Definition: jwt.h:2644
detail::void
j template void())
Definition: json.hpp:4822
jwt::details::map_of_claims::begin
const_iterator begin() const
Definition: jwt.h:2643
jwt::verify_ops::insensitive_string_claim::operator()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
Definition: jwt.h:3536
jwt::details::detector::value
std::false_type value
Definition: jwt.h:2117
jwt::algorithm::hs256
Definition: jwt.h:1767
jwt::verify_ops::date_before_claim::operator()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
Definition: jwt.h:3450
jwt::algorithm::ps384
Definition: jwt.h:2022
jwt::algorithm::hs384::hs384
hs384(std::string key)
Definition: jwt.h:1784
jwt::details::supports_end
Definition: jwt.h:2329
jwt::jwk::get_x5c
json_traits::array_type get_x5c() const
Definition: jwt.h:3932
jwt::details::map_of_claims::map_of_claims
map_of_claims()=default
jwt::error::rsa_error::get_key_failed
@ get_key_failed
jwt::decoded_jwt::payload_base64
json_traits::string_type payload_base64
Unmodified payload part in base64.
Definition: jwt.h:2942
jwt::basic_claim::basic_claim
JWT_CLAIM_EXPLICIT basic_claim(const date &d)
Definition: jwt.h:2507
jwt::header::get_header_claim
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:2920
jwt::verify_ops::date_before_claim::leeway
const size_t leeway
Definition: jwt.h:3449
jwt::algorithm::pss::sign
std::string sign(const std::string &data, std::error_code &ec) const
Definition: jwt.h:1638
jwt::error::signature_generation_error::signupdate_failed
@ signupdate_failed
jwt::details::supports_as_number::value
static constexpr auto value
Definition: jwt.h:2200
jwt::details::supports_as_array
Definition: jwt.h:2169
jwt::details::map_of_claims::cend
const_iterator cend() const
Definition: jwt.h:2642
jwt::algorithm::rs512
Definition: jwt.h:1840
jwt::jwks::begin
iterator begin()
Definition: jwt.h:4091
jwt::details::is_valid_traits::value
static constexpr auto value
Definition: jwt.h:2266
operator>>
std::istream & operator>>(std::istream &is, jwt::basic_claim< json_traits > &c)
Definition: jwt.h:4211
jwt::details::supports_begin::value
static constexpr auto value
Definition: jwt.h:2314
jwt::basic_claim::basic_claim
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v)
Definition: jwt.h:2512
jwt::decoded_jwt::get_header_claim
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:3077
jwt::jwks::has_jwk
bool has_jwk(const typename json_traits::string_type &key_id) const noexcept
Definition: jwt.h:4102
jwt::error::signature_generation_error::rsa_private_encrypt_failed
@ rsa_private_encrypt_failed
jwt::jwks::const_iterator
typename jwt_vector_t::const_iterator const_iterator
Definition: jwt.h:4074
jwt::details::make_void
Definition: jwt.h:2088
JWT_CLAIM_EXPLICIT
#define JWT_CLAIM_EXPLICIT
Definition: jwt.h:64
jwt::algorithm::rsa::sign
std::string sign(const std::string &data, std::error_code &ec) const
Definition: jwt.h:1057
jwt::details::as_array_function
decltype(traits_type::as_array) as_array_function
Definition: jwt.h:2163
jwt::algorithm::none
"none" algorithm.
Definition: jwt.h:915
jwt::decode
decoded_jwt< json_traits > decode(const typename json_traits::string_type &token)
Definition: jwt.h:4192
jwt::jwks::iterator
typename jwt_vector_t::iterator iterator
Definition: jwt.h:4073
jwt::decoded_jwt::token
const json_traits::string_type token
Unmodifed token, as passed to constructor.
Definition: jwt.h:2934
jwt::payload::get_issuer
json_traits::string_type get_issuer() const
Definition: jwt.h:2758
jwt::default_clock
Definition: jwt.h:4150
jwt::error::signature_generation_exception
Definition: jwt.h:90
jwt::error::signature_verification_error::set_rsa_pss_saltlen_failed
@ set_rsa_pss_saltlen_failed
jwt::error::token_verification_error::missing_claim
@ missing_claim
jwt::builder::set_header_claim
builder & set_header_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition: jwt.h:3100
jwt::details::map_of_claims::begin
iterator begin()
Definition: jwt.h:2639
jwt::error::signature_generation_error::ok
@ ok
jwt::builder::set_not_before
builder & set_not_before(const date &d)
Definition: jwt.h:3232
jwt::builder::set_expires_at
builder & set_expires_at(const date &d)
Definition: jwt.h:3223
jwt::details::is_valid_json_string::value
static constexpr auto value
Definition: jwt.h:2442
jwt::error::throw_if_error
void throw_if_error(std::error_code ec)
Definition: jwt.h:389
jwt::helper::bn2raw
std::string bn2raw(const BIGNUM *bn)
Definition: jwt.h:877
jwt::details::is_as_array_signature
typename std::is_same< as_array_function< traits_type >, array_type(const value_type &)> is_as_array_signature
Definition: jwt.h:2167
jwt::jwks
JWK Set.
Definition: jwt.h:4068
jwt::details::has_key_type
typename traits_type::key_type has_key_type
Definition: jwt.h:2295
jwt::algorithm::ed448::ed448
ed448(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1990
jwt::verify_ops::date_before_claim
Definition: jwt.h:3447
jwt::error::signature_generation_error::signinit_failed
@ signinit_failed
jwt::verify_ops::verify_context
Definition: jwt.h:3352
jwt::decoded_jwt::get_payload
const json_traits::string_type & get_payload() const noexcept
Definition: jwt.h:3013
jwt::algorithm::ecdsa::ecdsa
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)
Definition: jwt.h:1165
jwt::verify_ops::is_subset_claim::operator()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
Definition: jwt.h:3491
jwt::algorithm::ecdsa::verify
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition: jwt.h:1247
jwt::header::get_content_type
json_traits::string_type get_content_type() const
Definition: jwt.h:2893
jwt::jwks::cbegin
const_iterator cbegin() const
Definition: jwt.h:4093
jwt::algorithm::hs384
Definition: jwt.h:1778
jwt::date
std::chrono::system_clock::time_point date
Definition: jwt.h:79
jwt::verify_ops::verify_context::get_claim
basic_claim< json_traits > get_claim(bool in_header, std::error_code &ec) const
Definition: jwt.h:3369
jwt::error::rsa_error_category
std::error_category & rsa_error_category()
Error category for RSA errors.
Definition: jwt.h:125
jwt::verifier::with_audience
verifier & with_audience(const typename basic_claim_t::set_t &aud)
Definition: jwt.h:3731
jwt::details::is_detected_t
typename detector< nonesuch, void, Op, Args... >::type is_detected_t
Definition: jwt.h:2132
jwt::error::rsa_error::cert_load_failed
@ cert_load_failed
jwt::error::rsa_error::no_key_provided
@ no_key_provided
jwt::details::void_t
typename make_void< Ts... >::type void_t
Definition: jwt.h:2093
jwt::error::signature_verification_error
signature_verification_error
Errors related to verification of signatures.
Definition: jwt.h:210
jwt::json::type::boolean
@ boolean
jwt::error::rsa_error
rsa_error
Errors related to processing of RSA signatures.
Definition: jwt.h:109
jwt::algorithm::pss
Base class for PSS-RSA family of algorithms.
Definition: jwt.h:1604
jwt::parse_jwk
jwk< json_traits > parse_jwk(const typename json_traits::string_type &token)
Definition: jwt.h:4198
jwt::details::has_subcription_operator::test_operator_plus
static auto test_operator_plus(int) -> sfinae_true< decltype(std::declval< T >().operator[](std::declval< A0 >()))>
jwt::algorithm::rsa
Base class for RSA family of algorithms.
Definition: jwt.h:1024
jwt::details::supports_begin
Definition: jwt.h:2312
jwt::details::map_of_claims::operator=
map_of_claims & operator=(const map_of_claims &)=default
jwt::details::supports_end::value
static constexpr auto value
Definition: jwt.h:2331
jwt::error::signature_generation_error::digestupdate_failed
@ digestupdate_failed
jwt::jwk::has_jwk_claim
bool has_jwk_claim(const typename json_traits::string_type &name) const noexcept
Definition: jwt.h:4040
jwt::json::type::number
@ number
jwt::decoded_jwt::header_base64
json_traits::string_type header_base64
Unmodified header part in base64.
Definition: jwt.h:2938
jwt::algorithm::rsa::verify
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition: jwt.h:1101
jwt
JSON Web Token.
Definition: base.h:18
jwt::basic_claim::basic_claim
JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a)
Definition: jwt.h:2511
jwt::jwk::has_x5c
bool has_x5c() const noexcept
Definition: jwt.h:4022
jwt::verify_ops::equals_claim::expected
const basic_claim< json_traits > expected
Definition: jwt.h:3414
jwt::jwk::has_key_type
bool has_key_type() const noexcept
Definition: jwt.h:3980
jwt::basic_claim::basic_claim
basic_claim()=default
jwt::details::map_of_claims::cbegin
const_iterator cbegin() const
Definition: jwt.h:2641
jwt::verifier::verify
void verify(const decoded_jwt< json_traits > &jwt) const
Definition: jwt.h:3798
jwt::jwk::get_algorithm
json_traits::string_type get_algorithm() const
Definition: jwt.h:3898
jwt::details::is_as_string_signature
typename std::is_same< as_string_function< traits_type >, string_type(const value_type &)> is_as_string_signature
Definition: jwt.h:2181
jwt::details::supports_as_integer
Definition: jwt.h:2215
jwt::details::is_valid_traits
Definition: jwt.h:2242
jwt::algorithm::eddsa::sign
std::string sign(const std::string &data, std::error_code &ec) const
Definition: jwt.h:1480
jwt::payload::has_audience
bool has_audience() const noexcept
Definition: jwt.h:2731
jwt::builder::set_type
builder & set_type(typename json_traits::string_type str)
Definition: jwt.h:3159
jwt::decoded_jwt::get_payload_claim
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:3066
jwt::error::ecdsa_exception
Definition: jwt.h:98
jwt::header::has_header_claim
bool has_header_claim(const typename json_traits::string_type &name) const noexcept
Definition: jwt.h:2911
detail::detected_t
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition: json.hpp:298
jwt::verify_ops::is_subset_claim::expected
const basic_claim< json_traits >::set_t expected
Definition: jwt.h:3490
jwt::basic_claim::as_set
set_t as_set() const
Definition: jwt.h:2573
jwt::details::map_of_claims::end
iterator end()
Definition: jwt.h:2640
jwt::details::is_valid_json_object::value
static constexpr auto value
Definition: jwt.h:2375
jwt::error::invalid_json_exception
Definition: jwt.h:2607
jwt::algorithm::ps512
Definition: jwt.h:2042
jwt::algorithm::eddsa::eddsa
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)
Definition: jwt.h:1458
jwt::decoded_jwt::get_signature
const json_traits::string_type & get_signature() const noexcept
Definition: jwt.h:3018
jwt::details::is_substr_start_index_signature
typename std::is_same< decltype(std::declval< string_type >().substr(std::declval< integer_type >())), string_type > is_substr_start_index_signature
Definition: jwt.h:2405
jwt::details::has_operate_plus_method::sfinae_true
Definition: jwt.h:2409
jwt::details::supports_as_object
Definition: jwt.h:2154
jwt::error::token_verification_error::wrong_algorithm
@ wrong_algorithm
jwt::helper::load_public_ec_key_from_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.
Definition: jwt.h:752
jwt::basic_claim::operator=
basic_claim & operator=(const basic_claim &)=default
jwt::details::supports_as_number
Definition: jwt.h:2198
jwt::verify_ops::verify_context::verify_context
verify_context(date ctime, const decoded_jwt< json_traits > &j, size_t l)
Definition: jwt.h:3354
jwt::details::has_operate_plus_method::test_operator_plus
static auto test_operator_plus(int) -> sfinae_true< decltype(std::declval< T >().operator+(std::declval< A0 >()))>
jwt::json::type
type
Generic JSON types used in JWTs.
Definition: jwt.h:2071
jwt::details::is_std_operate_plus_signature
typename std::is_same< decltype(std::operator+(std::declval< string_type >(), std::declval< string_type >())), string_type > is_std_operate_plus_signature
Definition: jwt.h:2425
jwt::details::is_valid_json_types::value
static constexpr auto value
Definition: jwt.h:2458
jwt::payload::get_audience
basic_claim_t::set_t get_audience() const
Definition: jwt.h:2778
jwt::helper::load_private_ec_key_from_string
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.
Definition: jwt.h:823
jwt::algorithm::eddsa
Base class for EdDSA family of algorithms.
Definition: jwt.h:1446
jwt::error::signature_verification_exception
Definition: jwt.h:86
jwt::error::signature_verification_error::invalid_signature
@ invalid_signature
jwt::error::signature_verification_error::verifyinit_failed
@ verifyinit_failed
jwt::error::signature_verification_error::create_context_failed
@ create_context_failed
jwt::details::map_of_claims::map_of_claims
map_of_claims(typename json_traits::object_type json)
Definition: jwt.h:2637
jwt::payload::has_subject
bool has_subject() const noexcept
Definition: jwt.h:2726
jwt::payload::has_issuer
bool has_issuer() const noexcept
Definition: jwt.h:2721
jwt::verify_ops::insensitive_string_claim::to_lower_unicode
static std::string to_lower_unicode(const std::string &str, const std::locale &loc)
Definition: jwt.h:3547
jwt::error::invalid_json_exception::invalid_json_exception
invalid_json_exception()
Definition: jwt.h:2609
jwt::details::supports_as_integer::value
static constexpr auto value
Definition: jwt.h:2217
jwt::basic_claim::get_type
json::type get_type() const
Definition: jwt.h:2545
jwt::details::supports_as_boolean
Definition: jwt.h:2232
jwt::basic_claim::as_bool
json_traits::boolean_type as_bool() const
Definition: jwt.h:2592
jwt::verify_ops::verify_context::current_time
date current_time
Definition: jwt.h:3359
jwt::jwk::get_key_operations
basic_claim_t::set_t get_key_operations() const
Definition: jwt.h:3887
is_detected
jwt::algorithm::eddsa::verify
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition: jwt.h:1540
jwt::verify_ops::verify_context::get_claim
basic_claim< json_traits > get_claim(json::type t, std::error_code &ec) const
Definition: jwt.h:3403
jwt::algorithm::es256k::es256k
es256k(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1936
jwt::details::supports_get_type::value
static constexpr auto value
Definition: jwt.h:2143
jwt::details::map_of_claims::get_claims
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_claims() const
Definition: jwt.h:2687
jwt::verify_ops::verify_context::default_leeway
size_t default_leeway
Definition: jwt.h:3363
jwt::error::token_verification_error::token_expired
@ token_expired
jwt::payload::has_not_before
bool has_not_before() const noexcept
Definition: jwt.h:2741
jwt::verifier::issued_at_leeway
verifier & issued_at_leeway(size_t leeway)
Definition: jwt.h:3680
jwt::verifier::leeway
verifier & leeway(size_t leeway)
Definition: jwt.h:3647
jwt::error::signature_verification_error::verifyfinal_failed
@ verifyfinal_failed
jwt::error::signature_verification_error::verifyupdate_failed
@ verifyupdate_failed
jwt::algorithm::hs512
Definition: jwt.h:1789
jwt::details::supports_as_string
Definition: jwt.h:2183
jwt::jwk::get_use
json_traits::string_type get_use() const
Definition: jwt.h:3879
jwt::algorithm::rs256::rs256
rs256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1809
jwt::algorithm::es512::es512
es512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1915
jwt::payload::get_not_before
date get_not_before() const
Definition: jwt.h:2799
jwt::verify_ops::verify_context::get_claim
basic_claim< json_traits > get_claim(std::error_code &ec) const
Definition: jwt.h:3402
jwt::details::is_as_object_signature
typename std::is_same< as_object_function< traits_type >, object_type(const value_type &)> is_as_object_signature
Definition: jwt.h:2152
jwt::algorithm::es256k
Definition: jwt.h:1926
jwt::header::get_algorithm
json_traits::string_type get_algorithm() const
Definition: jwt.h:2873
jwt::details::has_mapped_type
typename traits_type::mapped_type has_mapped_type
Definition: jwt.h:2293
jwt::algorithm::ecdsa
Base class for ECDSA family of algorithms.
Definition: jwt.h:1152
jwt::header::header_claims
details::map_of_claims< json_traits > header_claims
Definition: jwt.h:2843
jwt::payload::get_subject
json_traits::string_type get_subject() const
Definition: jwt.h:2768
jwt::algorithm::hmacsha::name
std::string name() const
Definition: jwt.h:1011
jwt::decode
decoded_jwt< json_traits > decode(const typename json_traits::string_type &token, Decode decode)
Definition: jwt.h:4179
jwt::decoded_jwt::header
json_traits::string_type header
Header part decoded from base64.
Definition: jwt.h:2936
jwt::error::signature_verification_error::ok
@ ok
jwt::error::claim_not_present_exception
Definition: jwt.h:2614
jwt::payload::payload_claims
details::map_of_claims< json_traits > payload_claims
Definition: jwt.h:2712
jwt::details::is_as_boolean_signature
typename std::is_same< as_boolean_function< traits_type >, boolean_type(const value_type &)> is_as_boolean_signature
Definition: jwt.h:2229
jwt::jwk::get_jwk_claim
basic_claim_t get_jwk_claim(const typename json_traits::string_type &name) const
Definition: jwt.h:4050
jwt::algorithm::es384::es384
es384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1893
jwt::basic_claim::as_string
json_traits::string_type as_string() const
Definition: jwt.h:2552
jwt::decoded_jwt::get_payload_claims
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_payload_claims() const
Definition: jwt.h:3047
jwt::builder
Definition: jwt.h:3087
jwt::basic_claim::to_json
json_traits::value_type to_json() const
Definition: jwt.h:2526
jwt::jwks::begin
const_iterator begin() const
Definition: jwt.h:4095
jwt::details::as_number_function
decltype(traits_type::as_number) as_number_function
Definition: jwt.h:2192
jwt::verify_ops::verify_context::get_claim
basic_claim< json_traits > get_claim(bool in_header, json::type t, std::error_code &ec) const
Definition: jwt.h:3390
jwt::details::is_subcription_operator_signature::value
static constexpr auto value
Definition: jwt.h:2364
jwt::details::has_iterator
typename object_type::iterator has_iterator
Definition: jwt.h:2299
jwt::decoded_jwt::get_header_base64
const json_traits::string_type & get_header_base64() const noexcept
Definition: jwt.h:3023
jwt::details::is_valid_json_value::value
static constexpr auto value
Definition: jwt.h:2283
jwt::algorithm::es256::es256
es256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1871
jwt::error::signature_generation_error::digestinit_failed
@ digestinit_failed
jwt::details::get_type_function
decltype(traits_type::get_type) get_type_function
Definition: jwt.h:2135
jwt::payload::get_issued_at
date get_issued_at() const
Definition: jwt.h:2806
jwt::jwk::get_key_type
json_traits::string_type get_key_type() const
Definition: jwt.h:3868
jwt::decoded_jwt::get_signature_base64
const json_traits::string_type & get_signature_base64() const noexcept
Definition: jwt.h:3039
jwt::verify_ops::insensitive_string_claim::insensitive_string_claim
insensitive_string_claim(const typename json_traits::string_type &e, std::locale loc)
Definition: jwt.h:3531
jwt::verify_ops::date_after_claim::leeway
const size_t leeway
Definition: jwt.h:3469
jwt::details::nonesuch::~nonesuch
~nonesuch()=delete
jwt::jwk::has_x5u
bool has_x5u() const noexcept
Definition: jwt.h:4016
jwt::payload
Definition: jwt.h:2709
jwt::details::is_substr_start_end_index_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
Definition: jwt.h:2401
jwt::error::token_verification_error_category
std::error_category & token_verification_error_category()
Error category for token verification errors.
Definition: jwt.h:355
jwt::verifier::verify
void verify(const decoded_jwt< json_traits > &jwt, std::error_code &ec) const
Definition: jwt.h:3809
jwt::error::ecdsa_error::create_context_failed
@ create_context_failed
jwt::algorithm::rs384::rs384
rs384(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1829
jwt::algorithm::none::sign
std::string sign(const std::string &, std::error_code &ec) const
Return an empty string.
Definition: jwt.h:920
jwt::error::rsa_error::create_mem_bio_failed
@ create_mem_bio_failed
jwt::details::is_valid_json_value
Definition: jwt.h:2281
jwt::details::nonesuch::nonesuch
nonesuch()=delete
jwt::create
builder< json_traits > create()
Definition: jwt.h:4168
jwt::details::supports_as_boolean::value
static constexpr auto value
Definition: jwt.h:2234
jwt::details::supports_as_array::value
static constexpr auto value
Definition: jwt.h:2171
jwt::details::has_subcription_operator::value
static constexpr auto value
Definition: jwt.h:2353
jwt::error::signature_generation_error::rsa_padding_failed
@ rsa_padding_failed
jwt::basic_claim::basic_claim
basic_claim(Iterator begin, Iterator end)
Definition: jwt.h:2518
jwt::details::detector< Default, void_t< Op< Args... > >, Op, Args... >::type
Op< Args... > type
Definition: jwt.h:2125
jwt::algorithm::ed25519
Definition: jwt.h:1953
jwt::builder::sign
json_traits::string_type sign(const Algo &algo, std::error_code &ec) const
Definition: jwt.h:3336
jwt::builder::sign
json_traits::string_type sign(const Algo &algo) const
Definition: jwt.h:3283
jwt::decoded_jwt::get_payload_base64
const json_traits::string_type & get_payload_base64() const noexcept
Definition: jwt.h:3031
jwt::error::signature_generation_error::ecdsa_do_sign_failed
@ ecdsa_do_sign_failed
jwt::details::as_string_function
decltype(traits_type::as_string) as_string_function
Definition: jwt.h:2177
jwt::builder::set_issuer
builder & set_issuer(typename json_traits::string_type str)
Definition: jwt.h:3187
jwt::algorithm::ed25519::ed25519
ed25519(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:1964
jwt::details::is_begin_const_signature
typename std::is_same< decltype(std::declval< const object_type >().begin()), has_const_iterator< object_type > > is_begin_const_signature
Definition: jwt.h:2310
jwt::error::ecdsa_error::no_key_provided
@ no_key_provided
jwt::jwk::get_curve
json_traits::string_type get_curve() const
Get curve claim.
Definition: jwt.h:3924
jwt::verify_ops::date_after_claim::operator()
void operator()(const verify_context< json_traits > &ctx, std::error_code &ec) const
Definition: jwt.h:3470
jwt::verifier::with_audience
verifier & with_audience(const typename json_traits::string_type &aud)
Definition: jwt.h:3742
jwt::header
Definition: jwt.h:2840
jwt::builder::set_audience
builder & set_audience(typename json_traits::array_type a)
Definition: jwt.h:3205
jwt::algorithm::ps512::ps512
ps512(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:2051
jwt::details::supports_as_string::value
static constexpr auto value
Definition: jwt.h:2185
jwt::error::rsa_error::write_key_failed
@ write_key_failed
jwt::decoded_jwt::decoded_jwt
JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type &token)
Parses a given token.
Definition: jwt.h:2960
jwt::algorithm::hs256::hs256
hs256(std::string key)
Definition: jwt.h:1773
jwt::error::token_verification_error::ok
@ ok
jwt::details::is_subcription_operator_signature
Definition: jwt.h:2357
jwt::jwk::empty
bool empty() const noexcept
Definition: jwt.h:4055
jwt::jwk::get_x5c_key_value
json_traits::string_type get_x5c_key_value() const
Definition: jwt.h:3967
jwt::jwk::has_key_id
bool has_key_id() const noexcept
Definition: jwt.h:4010
jwt::algorithm::hs512::hs512
hs512(std::string key)
Definition: jwt.h:1795
jwt::jwk::jwk
JWT_CLAIM_EXPLICIT jwk(const typename json_traits::value_type &json)
Definition: jwt.h:3855
jwt::algorithm::ed448
Definition: jwt.h:1979
jwt::basic_claim::as_number
json_traits::number_type as_number() const
Definition: jwt.h:2599
jwt::jwk::has_algorithm
bool has_algorithm() const noexcept
Definition: jwt.h:3998
jwt::builder::sign
json_traits::string_type sign(const Algo &algo, Encode encode, std::error_code &ec) const
Definition: jwt.h:3305
jwt::error::ecdsa_error
ecdsa_error
Errors related to processing of RSA signatures.
Definition: jwt.h:161
jwt::algorithm::rsa::name
std::string name() const
Definition: jwt.h:1139
jwt::verifier::expires_at_leeway
verifier & expires_at_leeway(size_t leeway)
Definition: jwt.h:3658
jwt::details::detector::type
Default type
Definition: jwt.h:2118
jwt::decoded_jwt::get_header_claims
std::unordered_map< typename json_traits::string_type, basic_claim_t > get_header_claims() const
Definition: jwt.h:3055
jwt::jwk::get_x5u
json_traits::string_type get_x5u() const
Definition: jwt.h:3940
jwt::basic_claim::operator>>
std::istream & operator>>(std::istream &is)
Definition: jwt.h:2532
jwt::algorithm::es256
Definition: jwt.h:1860
jwt::json::type::array
@ array
jwt::error::signature_generation_error::signfinal_failed
@ signfinal_failed
jwt::error::signature_generation_error
signature_generation_error
Errors related to signature generation errors.
Definition: jwt.h:267
jwt::error::token_verification_exception
Definition: jwt.h:102
jwt::jwk::has_key_operations
bool has_key_operations() const noexcept
Definition: jwt.h:3992
jwt::error::claim_not_present_exception::claim_not_present_exception
claim_not_present_exception()
Definition: jwt.h:2616
jwt::details::as_object_function
decltype(traits_type::as_object) as_object_function
Definition: jwt.h:2148
jwt::details::is_detected
typename detector< nonesuch, void, Op, Args... >::value is_detected
Definition: jwt.h:2129
jwt::details::is_valid_json_object
Definition: jwt.h:2373
jwt::error::token_verification_error::claim_type_missmatch
@ claim_type_missmatch
jwt::payload::get_id
json_traits::string_type get_id() const
Definition: jwt.h:2813
jwt::algorithm::ps256::ps256
ps256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Definition: jwt.h:2011
jwt::verify_ops::equals_claim
Definition: jwt.h:3412
jwt::builder::set_audience
builder & set_audience(typename json_traits::string_type aud)
Definition: jwt.h:3214
jwt::jwks::jwt_vector_t
std::vector< jwk_t > jwt_vector_t
Definition: jwt.h:4072
jwt::details::has_value_type
typename traits_type::value_type has_value_type
Definition: jwt.h:2297
jwt::details::is_valid_json_string::substr
static constexpr auto substr
Definition: jwt.h:2429
jwt::error::token_verification_error::audience_missmatch
@ audience_missmatch
jwt::algorithm::hmacsha::hmacsha
hmacsha(std::string key, const EVP_MD *(*md)(), std::string name)
Definition: jwt.h:955
jwt::header::has_content_type
bool has_content_type() const noexcept
Definition: jwt.h:2861
jwt::basic_claim
a class to store a generic JSON value as claim
Definition: jwt.h:2473
jwt::error::signature_generation_error::create_context_failed
@ create_context_failed
jwt::parse_jwks
jwks< json_traits > parse_jwks(const typename json_traits::string_type &token)
Definition: jwt.h:4204
jwt::basic_claim::as_int
json_traits::integer_type as_int() const
Definition: jwt.h:2585
jwt::basic_claim::as_array
json_traits::array_type as_array() const
Definition: jwt.h:2566
jwt::details::map_of_claims::has_claim
bool has_claim(const typename json_traits::string_type &name) const noexcept
Definition: jwt.h:2668
jwt::error::signature_generation_error::get_key_failed
@ get_key_failed
jwt::jwk::get_key_id
json_traits::string_type get_key_id() const
Definition: jwt.h:3909
jwt::details::detector
Definition: jwt.h:2115
jwt::algorithm::hmacsha::verify
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition: jwt.h:988
jwt::details::is_begin_signature
typename std::is_same< decltype(std::declval< object_type >().begin()), has_iterator< object_type > > is_begin_signature
Definition: jwt.h:2305
jwt::default_clock::now
date now() const
Definition: jwt.h:4152
jwt::verifier::with_claim
verifier & with_claim(const typename json_traits::string_type &name, basic_claim_t c)
Definition: jwt.h:3777
jwt::details::has_operate_plus_method::value
static constexpr auto value
Definition: jwt.h:2418
jwt::details::nonesuch
Definition: jwt.h:2103
jwt::details::is_valid_json_string
Definition: jwt.h:2427
jwt::jwks::get_jwk
jwk_t get_jwk(const typename json_traits::string_type &key_id) const
Definition: jwt.h:4112