+
+
+
4#ifndef JWT_DISABLE_PICOJSON
+
5#ifndef PICOJSON_USE_INT64
+
6#define PICOJSON_USE_INT64
+
+
8#include "picojson/picojson.h"
+
+
+
11#ifndef JWT_DISABLE_BASE64
+
+
+
+
15#include <openssl/ec.h>
+
16#include <openssl/ecdsa.h>
+
17#include <openssl/err.h>
+
18#include <openssl/evp.h>
+
19#include <openssl/hmac.h>
+
20#include <openssl/pem.h>
+
21#include <openssl/rsa.h>
+
22#include <openssl/ssl.h>
+
+
+
+
+
+
+
+
+
+
+
+
34#include <system_error>
+
+
36#include <unordered_map>
+
+
+
+
40#if __cplusplus > 201103L
+
+
+
+
44#if __cplusplus >= 201402L
+
+
46#if __has_include(<experimental/type_traits>)
+
47#include <experimental/type_traits>
+
+
+
+
+
52#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
53#define JWT_OPENSSL_3_0
+
54#elif OPENSSL_VERSION_NUMBER >= 0x10101000L
+
55#define JWT_OPENSSL_1_1_1
+
56#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
+
57#define JWT_OPENSSL_1_1_0
+
58#elif OPENSSL_VERSION_NUMBER >= 0x10000000L
+
59#define JWT_OPENSSL_1_0_0
+
+
+
62#if defined(LIBRESSL_VERSION_NUMBER)
+
63#if LIBRESSL_VERSION_NUMBER >= 0x3050300fL
+
64#define JWT_OPENSSL_1_1_0
+
+
66#define JWT_OPENSSL_1_0_0
+
+
+
+
70#if defined(LIBWOLFSSL_VERSION_HEX)
+
71#define JWT_OPENSSL_1_1_1
+
+
+
74#ifndef JWT_CLAIM_EXPLICIT
+
75#define JWT_CLAIM_EXPLICIT explicit
+
+
+
+
89 using date = std::chrono::system_clock::time_point;
+
+
+
+
+
+
96 using system_error::system_error;
+
+
+
+
+
99 using system_error::system_error;
+
+
+
+
+
102 using system_error::system_error;
+
+
+
+
+
105 using system_error::system_error;
+
+
+
+
+
108 using system_error::system_error;
+
+
+
+
+
+
115 cert_load_failed = 10,
+
+
+
+
119 convert_to_pem_failed,
+
+
+
122 create_mem_bio_failed,
+
+
+
+
+
+
129 class rsa_error_cat :
public std::error_category {
+
+
131 const char* name()
const noexcept override {
return "rsa_error"; };
+
132 std::string message(
int ev)
const override {
+
+
134 case rsa_error::ok:
return "no error";
+
135 case rsa_error::cert_load_failed:
return "error loading cert into memory";
+
136 case rsa_error::get_key_failed:
return "error getting key from certificate";
+
137 case rsa_error::write_key_failed:
return "error writing key data in PEM format";
+
138 case rsa_error::write_cert_failed:
return "error writing cert data in PEM format";
+
139 case rsa_error::convert_to_pem_failed:
return "failed to convert key to pem";
+
140 case rsa_error::load_key_bio_write:
return "failed to load key: bio write failed";
+
141 case rsa_error::load_key_bio_read:
return "failed to load key: bio read failed";
+
142 case rsa_error::create_mem_bio_failed:
return "failed to create memory bio";
+
143 case rsa_error::no_key_provided:
return "at least one of public or private key need to be present";
+
144 default:
return "unknown RSA error";
+
+
+
+
148 static rsa_error_cat cat;
+
+
+
+
+
+
+
+
+
158 load_key_bio_write = 10,
+
+
160 create_mem_bio_failed,
+
+
+
+
164 create_context_failed
+
+
+
+
+
170 class ecdsa_error_cat :
public std::error_category {
+
+
172 const char* name()
const noexcept override {
return "ecdsa_error"; };
+
173 std::string message(
int ev)
const override {
+
+
175 case ecdsa_error::ok:
return "no error";
+
176 case ecdsa_error::load_key_bio_write:
return "failed to load key: bio write failed";
+
177 case ecdsa_error::load_key_bio_read:
return "failed to load key: bio read failed";
+
178 case ecdsa_error::create_mem_bio_failed:
return "failed to create memory bio";
+
179 case ecdsa_error::no_key_provided:
+
180 return "at least one of public or private key need to be present";
+
181 case ecdsa_error::invalid_key_size:
return "invalid key size";
+
182 case ecdsa_error::invalid_key:
return "invalid key";
+
183 case ecdsa_error::create_context_failed:
return "failed to create context";
+
184 default:
return "unknown ECDSA error";
+
+
+
+
188 static ecdsa_error_cat cat;
+
+
+
+
+
+
+
+
+
+
199 invalid_signature = 10,
+
200 create_context_failed,
+
+
+
+
+
205 set_rsa_pss_saltlen_failed,
+
206 signature_encoding_failed
+
+
+
+
+
212 class verification_error_cat :
public std::error_category {
+
+
214 const char* name()
const noexcept override {
return "signature_verification_error"; };
+
215 std::string message(
int ev)
const override {
+
+
217 case signature_verification_error::ok:
return "no error";
+
218 case signature_verification_error::invalid_signature:
return "invalid signature";
+
219 case signature_verification_error::create_context_failed:
+
220 return "failed to verify signature: could not create context";
+
221 case signature_verification_error::verifyinit_failed:
+
222 return "failed to verify signature: VerifyInit failed";
+
223 case signature_verification_error::verifyupdate_failed:
+
224 return "failed to verify signature: VerifyUpdate failed";
+
225 case signature_verification_error::verifyfinal_failed:
+
226 return "failed to verify signature: VerifyFinal failed";
+
227 case signature_verification_error::get_key_failed:
+
228 return "failed to verify signature: Could not get key";
+
229 case signature_verification_error::set_rsa_pss_saltlen_failed:
+
230 return "failed to verify signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
+
231 case signature_verification_error::signature_encoding_failed:
+
232 return "failed to verify signature: i2d_ECDSA_SIG failed";
+
233 default:
return "unknown signature verification error";
+
+
+
+
237 static verification_error_cat cat;
+
+
+
+
+
+
+
+
+
+
+
+
+
251 create_context_failed,
+
+
+
+
255 ecdsa_do_sign_failed,
+
+
+
+
+
260 rsa_private_encrypt_failed,
+
+
262 set_rsa_pss_saltlen_failed,
+
263 signature_decoding_failed
+
+
+
+
+
269 class signature_generation_error_cat :
public std::error_category {
+
+
271 const char* name()
const noexcept override {
return "signature_generation_error"; };
+
272 std::string message(
int ev)
const override {
+
+
274 case signature_generation_error::ok:
return "no error";
+
275 case signature_generation_error::hmac_failed:
return "hmac failed";
+
276 case signature_generation_error::create_context_failed:
+
277 return "failed to create signature: could not create context";
+
278 case signature_generation_error::signinit_failed:
+
279 return "failed to create signature: SignInit failed";
+
280 case signature_generation_error::signupdate_failed:
+
281 return "failed to create signature: SignUpdate failed";
+
282 case signature_generation_error::signfinal_failed:
+
283 return "failed to create signature: SignFinal failed";
+
284 case signature_generation_error::ecdsa_do_sign_failed:
return "failed to generate ecdsa signature";
+
285 case signature_generation_error::digestinit_failed:
+
286 return "failed to create signature: DigestInit failed";
+
287 case signature_generation_error::digestupdate_failed:
+
288 return "failed to create signature: DigestUpdate failed";
+
289 case signature_generation_error::digestfinal_failed:
+
290 return "failed to create signature: DigestFinal failed";
+
291 case signature_generation_error::rsa_padding_failed:
+
292 return "failed to create signature: EVP_PKEY_CTX_set_rsa_padding failed";
+
293 case signature_generation_error::rsa_private_encrypt_failed:
+
294 return "failed to create signature: RSA_private_encrypt failed";
+
295 case signature_generation_error::get_key_failed:
+
296 return "failed to generate signature: Could not get key";
+
297 case signature_generation_error::set_rsa_pss_saltlen_failed:
+
298 return "failed to create signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
+
299 case signature_generation_error::signature_decoding_failed:
+
300 return "failed to create signature: d2i_ECDSA_SIG failed";
+
301 default:
return "unknown signature generation error";
+
+
+
+
305 static signature_generation_error_cat cat = {};
+
+
+
+
+
+
+
+
+
+
+
+
318 wrong_algorithm = 10,
+
+
320 claim_type_missmatch,
+
321 claim_value_missmatch,
+
+
+
+
+
+
+
329 class token_verification_error_cat :
public std::error_category {
+
+
331 const char* name()
const noexcept override {
return "token_verification_error"; };
+
332 std::string message(
int ev)
const override {
+
+
334 case token_verification_error::ok:
return "no error";
+
335 case token_verification_error::wrong_algorithm:
return "wrong algorithm";
+
336 case token_verification_error::missing_claim:
return "decoded JWT is missing required claim(s)";
+
337 case token_verification_error::claim_type_missmatch:
+
338 return "claim type does not match expected type";
+
339 case token_verification_error::claim_value_missmatch:
+
340 return "claim value does not match expected value";
+
341 case token_verification_error::token_expired:
return "token expired";
+
342 case token_verification_error::audience_missmatch:
+
343 return "token doesn't contain the required audience";
+
344 default:
return "unknown token verification error";
+
+
+
+
348 static token_verification_error_cat cat = {};
+
+
+
+
+
+
+
+
+
356 inline void throw_if_error(std::error_code ec) {
+
+
+
+
+
361 throw signature_verification_exception(ec);
+
+
+
+
+
+
+
+
+
+
+
371 struct is_error_code_enum<
jwt::error::rsa_error> : true_type {};
+
+
373 struct is_error_code_enum<
jwt::error::ecdsa_error> : true_type {};
+
+
375 struct is_error_code_enum<
jwt::error::signature_verification_error> : true_type {};
+
+
377 struct is_error_code_enum<
jwt::error::signature_generation_error> : true_type {};
+
+
379 struct is_error_code_enum<
jwt::error::token_verification_error> : true_type {};
+
+
+
+
+
+
+
+
+
+
401#ifdef JWT_OPENSSL_1_0_0
+
406 explicit evp_pkey_handle(EVP_PKEY* key) { m_key = std::shared_ptr<EVP_PKEY>(key, EVP_PKEY_free); }
+
+
408 EVP_PKEY* get()
const noexcept {
return m_key.get(); }
+
409 bool operator!()
const noexcept {
return m_key ==
nullptr; }
+
410 explicit operator bool()
const noexcept {
return m_key !=
nullptr; }
+
+
+
413 std::shared_ptr<EVP_PKEY> m_key{
nullptr};
+
+
+
420 evp_pkey_handle(
const evp_pkey_handle& other) : m_key{other.m_key} {
+
421 if (m_key !=
nullptr && EVP_PKEY_up_ref(m_key) != 1)
throw std::runtime_error(
"EVP_PKEY_up_ref failed");
+
+
+
424#if __cplusplus >= 201402L
+
+
+
427 evp_pkey_handle(evp_pkey_handle&& other) noexcept
+
428 : m_key{other.m_key} {
+
429 other.m_key =
nullptr;
+
+
431 evp_pkey_handle& operator=(
const evp_pkey_handle& other) {
+
432 if (&other ==
this)
return *
this;
+
433 decrement_ref_count(m_key);
+
+
435 increment_ref_count(m_key);
+
+
+
438 evp_pkey_handle& operator=(evp_pkey_handle&& other)
noexcept {
+
439 if (&other ==
this)
return *
this;
+
440 decrement_ref_count(m_key);
+
+
442 other.m_key =
nullptr;
+
+
+
445 evp_pkey_handle& operator=(EVP_PKEY* key) {
+
446 decrement_ref_count(m_key);
+
+
448 increment_ref_count(m_key);
+
+
+
451 ~evp_pkey_handle() noexcept { decrement_ref_count(m_key); }
+
+
453 EVP_PKEY* get() const noexcept {
return m_key; }
+
454 bool operator!() const noexcept {
return m_key ==
nullptr; }
+
455 explicit operator bool() const noexcept {
return m_key !=
nullptr; }
+
+
+
458 EVP_PKEY* m_key{
nullptr};
+
+
460 static void increment_ref_count(EVP_PKEY* key) {
+
461 if (key !=
nullptr && EVP_PKEY_up_ref(key) != 1)
throw std::runtime_error(
"EVP_PKEY_up_ref failed");
+
+
463 static void decrement_ref_count(EVP_PKEY* key)
noexcept {
+
464 if (key !=
nullptr) EVP_PKEY_free(key);
+
+
+
+
+
+
469 inline std::unique_ptr<BIO,
decltype(&BIO_free_all)> make_mem_buf_bio() {
+
470 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(BIO_new(BIO_s_mem()), BIO_free_all);
+
+
+
473 inline std::unique_ptr<BIO,
decltype(&BIO_free_all)> make_mem_buf_bio(
const std::string& data) {
+
474 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(
+
475#
if OPENSSL_VERSION_NUMBER <= 0x10100003L
+
476 BIO_new_mem_buf(
const_cast<char*
>(data.data()),
static_cast<int>(data.size())), BIO_free_all
+
+
478 BIO_new_mem_buf(data.data(),
static_cast<int>(data.size())), BIO_free_all
+
+
+
+
+
483 inline std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> make_evp_md_ctx() {
+
+
485#ifdef JWT_OPENSSL_1_0_0
+
486 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), &EVP_MD_CTX_destroy);
+
+
488 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), &EVP_MD_CTX_free);
+
+
+
+
+
+
500 std::error_code& ec) {
+
+
502 auto certbio = make_mem_buf_bio(certstr);
+
503 auto keybio = make_mem_buf_bio();
+
504 if (!certbio || !keybio) {
+
505 ec = error::rsa_error::create_mem_bio_failed;
+
+
+
+
509 std::unique_ptr<X509,
decltype(&X509_free)> cert(
+
510 PEM_read_bio_X509(certbio.get(),
nullptr,
nullptr,
const_cast<char*
>(pw.c_str())), X509_free);
+
+
512 ec = error::rsa_error::cert_load_failed;
+
+
+
515 std::unique_ptr<EVP_PKEY,
decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()), EVP_PKEY_free);
+
+
517 ec = error::rsa_error::get_key_failed;
+
+
+
520 if (PEM_write_bio_PUBKEY(keybio.get(), key.get()) == 0) {
+
521 ec = error::rsa_error::write_key_failed;
+
+
+
+
525 auto len = BIO_get_mem_data(keybio.get(), &ptr);
+
526 if (len <= 0 || ptr ==
nullptr) {
+
527 ec = error::rsa_error::convert_to_pem_failed;
+
+
+
530 return {ptr,
static_cast<size_t>(len)};
+
+
+
+
+
+
+
+
543 error::throw_if_error(ec);
+
+
+
+
+
+
+
+
+
556 auto c_str =
reinterpret_cast<const unsigned char*
>(cert_der_str.c_str());
+
+
558 std::unique_ptr<X509,
decltype(&X509_free)> cert(
+
559 d2i_X509(NULL, &c_str,
static_cast<int>(cert_der_str.size())), X509_free);
+
560 auto certbio = make_mem_buf_bio();
+
561 if (!cert || !certbio) {
+
562 ec = error::rsa_error::create_mem_bio_failed;
+
+
+
+
566 if (!PEM_write_bio_X509(certbio.get(), cert.get())) {
+
567 ec = error::rsa_error::write_cert_failed;
+
+
+
+
+
572 const auto len = BIO_get_mem_data(certbio.get(), &ptr);
+
573 if (len <= 0 || ptr ==
nullptr) {
+
574 ec = error::rsa_error::convert_to_pem_failed;
+
+
+
+
578 return {ptr,
static_cast<size_t>(len)};
+
+
+
+
595 template<
typename Decode>
+
+
+
597 std::error_code& ec) {
+
+
599 const auto decoded_str =
decode(cert_base64_der_str);
+
+
+
+
+
617 template<
typename Decode>
+
+
+
+
+
621 error::throw_if_error(ec);
+
+
+
+
+
+
+
+
+
634 error::throw_if_error(ec);
+
+
+
+
+
638#ifndef JWT_DISABLE_BASE64
+
+
+
649 auto decode = [](
const std::string& token) {
+
650 return base::decode<alphabet::base64>(base::pad<alphabet::base64>(token));
+
+
+
+
+
+
+
+
+
+
667 error::throw_if_error(ec);
+
+
+
+
+
+
+
681 std::error_code& ec) {
+
+
683 auto pubkey_bio = make_mem_buf_bio();
+
+
685 ec = error::rsa_error::create_mem_bio_failed;
+
+
+
688 if (key.substr(0, 27) ==
"-----BEGIN CERTIFICATE-----") {
+
+
+
691 const int len =
static_cast<int>(epkey.size());
+
692 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len) {
+
693 ec = error::rsa_error::load_key_bio_write;
+
+
+
+
697 const int len =
static_cast<int>(key.size());
+
698 if (BIO_write(pubkey_bio.get(), key.data(), len) != len) {
+
699 ec = error::rsa_error::load_key_bio_write;
+
+
+
+
+
+
705 pubkey_bio.get(),
nullptr,
nullptr,
+
706 (
void*)password.data()));
+
707 if (!pkey) ec = error::rsa_error::load_key_bio_read;
+
+
+
+
+
+
+
+
+
723 error::throw_if_error(ec);
+
+
+
+
+
+
+
735 std::error_code& ec) {
+
736 auto privkey_bio = make_mem_buf_bio();
+
+
738 ec = error::rsa_error::create_mem_bio_failed;
+
+
+
741 const int len =
static_cast<int>(key.size());
+
742 if (BIO_write(privkey_bio.get(), key.data(), len) != len) {
+
743 ec = error::rsa_error::load_key_bio_write;
+
+
+
+
747 PEM_read_bio_PrivateKey(privkey_bio.get(),
nullptr,
nullptr,
const_cast<char*
>(password.c_str())));
+
748 if (!pkey) ec = error::rsa_error::load_key_bio_read;
+
+
+
+
+
+
+
+
+
762 error::throw_if_error(ec);
+
+
+
+
+
+
+
776 std::error_code& ec) {
+
+
778 auto pubkey_bio = make_mem_buf_bio();
+
+
780 ec = error::ecdsa_error::create_mem_bio_failed;
+
+
+
783 if (key.substr(0, 27) ==
"-----BEGIN CERTIFICATE-----") {
+
+
+
786 const int len =
static_cast<int>(epkey.size());
+
787 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len) {
+
788 ec = error::ecdsa_error::load_key_bio_write;
+
+
+
+
792 const int len =
static_cast<int>(key.size());
+
793 if (BIO_write(pubkey_bio.get(), key.data(), len) != len) {
+
794 ec = error::ecdsa_error::load_key_bio_write;
+
+
+
+
+
+
800 pubkey_bio.get(),
nullptr,
nullptr,
+
801 (
void*)password.data()));
+
802 if (!pkey) ec = error::ecdsa_error::load_key_bio_read;
+
+
+
+
+
+
+
816 const std::string& password =
"") {
+
+
+
819 error::throw_if_error(ec);
+
+
+
+
+
+
+
831 std::error_code& ec) {
+
832 auto privkey_bio = make_mem_buf_bio();
+
+
834 ec = error::ecdsa_error::create_mem_bio_failed;
+
+
+
837 const int len =
static_cast<int>(key.size());
+
838 if (BIO_write(privkey_bio.get(), key.data(), len) != len) {
+
839 ec = error::ecdsa_error::load_key_bio_write;
+
+
+
+
843 PEM_read_bio_PrivateKey(privkey_bio.get(),
nullptr,
nullptr,
const_cast<char*
>(password.c_str())));
+
844 if (!pkey) ec = error::ecdsa_error::load_key_bio_read;
+
+
+
+
+
+
+
856 const std::string& password =
"") {
+
+
+
859 error::throw_if_error(ec);
+
+
+
+
+
+
869#ifdef JWT_OPENSSL_1_0_0
+
+
+
+
+
+
+
+
+
877 std::string res(BN_num_bytes(bn),
'\0');
+
878 BN_bn2bin(bn, (
unsigned char*)res.data());
+
+
+
+
+
886 inline std::unique_ptr<BIGNUM,
decltype(&BN_free)>
raw2bn(
const std::string& raw) {
+
887 return std::unique_ptr<BIGNUM, decltype(&BN_free)>(
+
888 BN_bin2bn(
reinterpret_cast<const unsigned char*
>(raw.data()),
static_cast<int>(raw.size()),
nullptr),
+
+
+
+
+
+
+
+
902 namespace algorithm {
+
+
914 std::string sign(
const std::string& , std::error_code& ec)
const {
+
+
+
+
925 void verify(
const std::string& ,
const std::string& signature, std::error_code& ec)
const {
+
+
927 if (!signature.empty()) { ec = error::signature_verification_error::invalid_signature; }
+
+
930 std::string name()
const {
return "none"; }
+
+
+
942 hmacsha(std::string key,
const EVP_MD* (*md)(), std::string name)
+
943 : secret(std::move(key)), md(md), alg_name(std::move(name)) {}
+
950 std::string sign(
const std::string& data, std::error_code& ec)
const {
+
+
952 std::string res(
static_cast<size_t>(EVP_MAX_MD_SIZE),
'\0');
+
953 auto len =
static_cast<unsigned int>(res.size());
+
954 if (HMAC(md(), secret.data(),
static_cast<int>(secret.size()),
+
955 reinterpret_cast<const unsigned char*
>(data.data()),
static_cast<int>(data.size()),
+
956 (
unsigned char*)res.data(),
+
+
958 ec = error::signature_generation_error::hmac_failed;
+
+
+
+
+
+
970 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const {
+
+
972 auto res = sign(data, ec);
+
+
+
+
976 for (
size_t i = 0; i < std::min<size_t>(res.size(), signature.size()); i++)
+
977 if (res[i] != signature[i]) matched =
false;
+
978 if (res.size() != signature.size()) matched =
false;
+
+
980 ec = error::signature_verification_error::invalid_signature;
+
+
+
+
988 std::string name()
const {
return alg_name; }
+
+
+
992 const std::string secret;
+
994 const EVP_MD* (*md)();
+
996 const std::string alg_name;
+
+
+
1011 rsa(
const std::string& public_key,
const std::string& private_key,
const std::string& public_key_password,
+
1012 const std::string& private_key_password,
const EVP_MD* (*md)(), std::string name)
+
1013 : md(md), alg_name(std::move(name)) {
+
1014 if (!private_key.empty()) {
+
+
1016 }
else if (!public_key.empty()) {
+
+
+
+
+
1027 std::string sign(
const std::string& data, std::error_code& ec)
const {
+
+
1029 auto ctx = helper::make_evp_md_ctx();
+
+
1031 ec = error::signature_generation_error::create_context_failed;
+
+
+
1034 if (!EVP_SignInit(ctx.get(), md())) {
+
1035 ec = error::signature_generation_error::signinit_failed;
+
+
+
+
1039 std::string res(EVP_PKEY_size(pkey.get()),
'\0');
+
1040 unsigned int len = 0;
+
+
1042 if (!EVP_SignUpdate(ctx.get(), data.data(), data.size())) {
+
1043 ec = error::signature_generation_error::signupdate_failed;
+
+
+
1046 if (EVP_SignFinal(ctx.get(), (
unsigned char*)res.data(), &len, pkey.get()) == 0) {
+
1047 ec = error::signature_generation_error::signfinal_failed;
+
+
+
+
+
+
+
1060 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const {
+
+
1062 auto ctx = helper::make_evp_md_ctx();
+
+
1064 ec = error::signature_verification_error::create_context_failed;
+
+
+
1067 if (!EVP_VerifyInit(ctx.get(), md())) {
+
1068 ec = error::signature_verification_error::verifyinit_failed;
+
+
+
1071 if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size())) {
+
1072 ec = error::signature_verification_error::verifyupdate_failed;
+
+
+
1075 auto res = EVP_VerifyFinal(ctx.get(),
reinterpret_cast<const unsigned char*
>(signature.data()),
+
1076 static_cast<unsigned int>(signature.size()), pkey.get());
+
+
1078 ec = error::signature_verification_error::verifyfinal_failed;
+
+
+
+
1086 std::string name()
const {
return alg_name; }
+
+
+
+
1092 const EVP_MD* (*md)();
+
1094 const std::string alg_name;
+
+
+
1111 ecdsa(
const std::string& public_key,
const std::string& private_key,
const std::string& public_key_password,
+
1112 const std::string& private_key_password,
const EVP_MD* (*md)(), std::string name,
size_t siglen)
+
1113 : md(md), alg_name(std::move(name)), signature_length(siglen) {
+
1114 if (!private_key.empty()) {
+
+
1116 check_private_key(pkey.get());
+
1117 }
else if (!public_key.empty()) {
+
+
1119 check_public_key(pkey.get());
+
+
+
+
+
+
1125 size_t keysize = EVP_PKEY_bits(pkey.get());
+
1126 if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
+
+
+
+
1136 std::string sign(
const std::string& data, std::error_code& ec)
const {
+
+
1138 auto ctx = helper::make_evp_md_ctx();
+
+
1140 ec = error::signature_generation_error::create_context_failed;
+
+
+
1143 if (!EVP_DigestSignInit(ctx.get(),
nullptr, md(),
nullptr, pkey.get())) {
+
1144 ec = error::signature_generation_error::signinit_failed;
+
+
+
1147 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size())) {
+
1148 ec = error::signature_generation_error::digestupdate_failed;
+
+
+
+
+
1153 if (!EVP_DigestSignFinal(ctx.get(),
nullptr, &len)) {
+
1154 ec = error::signature_generation_error::signfinal_failed;
+
+
+
1157 std::string res(len,
'\0');
+
1158 if (!EVP_DigestSignFinal(ctx.get(), (
unsigned char*)res.data(), &len)) {
+
1159 ec = error::signature_generation_error::signfinal_failed;
+
+
+
+
+
1164 return der_to_p1363_signature(res, ec);
+
+
+
1173 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const {
+
+
1175 std::string der_signature = p1363_to_der_signature(signature, ec);
+
+
+
1178 auto ctx = helper::make_evp_md_ctx();
+
+
1180 ec = error::signature_verification_error::create_context_failed;
+
+
+
1183 if (!EVP_DigestVerifyInit(ctx.get(),
nullptr, md(),
nullptr, pkey.get())) {
+
1184 ec = error::signature_verification_error::verifyinit_failed;
+
+
+
1187 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size())) {
+
1188 ec = error::signature_verification_error::verifyupdate_failed;
+
+
+
+
1192#if OPENSSL_VERSION_NUMBER < 0x10002000L
+
1193 unsigned char* der_sig_data =
reinterpret_cast<unsigned char*
>(
const_cast<char*
>(der_signature.data()));
+
+
1195 const unsigned char* der_sig_data =
reinterpret_cast<const unsigned char*
>(der_signature.data());
+
+
+
1198 EVP_DigestVerifyFinal(ctx.get(), der_sig_data,
static_cast<unsigned int>(der_signature.length()));
+
+
1200 ec = error::signature_verification_error::invalid_signature;
+
+
+
+
1204 ec = error::signature_verification_error::verifyfinal_failed;
+
+
+
+
1212 std::string name()
const {
return alg_name; }
+
+
+
1215 static void check_public_key(EVP_PKEY* pkey) {
+
1216#ifdef JWT_OPENSSL_3_0
+
1217 std::unique_ptr<EVP_PKEY_CTX,
decltype(&EVP_PKEY_CTX_free)> ctx(
+
1218 EVP_PKEY_CTX_new_from_pkey(
nullptr, pkey,
nullptr), EVP_PKEY_CTX_free);
+
+
1220 if (EVP_PKEY_public_check(ctx.get()) != 1) {
+
+
+
+
1224 std::unique_ptr<EC_KEY,
decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
+
+
+
+
+
+
1230 static void check_private_key(EVP_PKEY* pkey) {
+
1231#ifdef JWT_OPENSSL_3_0
+
1232 std::unique_ptr<EVP_PKEY_CTX,
decltype(&EVP_PKEY_CTX_free)> ctx(
+
1233 EVP_PKEY_CTX_new_from_pkey(
nullptr, pkey,
nullptr), EVP_PKEY_CTX_free);
+
+
1235 if (EVP_PKEY_private_check(ctx.get()) != 1) {
+
+
+
+
1239 std::unique_ptr<EC_KEY,
decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
+
+
+
+
+
+
1245 std::string der_to_p1363_signature(
const std::string& der_signature, std::error_code& ec)
const {
+
1246 const unsigned char* possl_signature =
reinterpret_cast<const unsigned char*
>(der_signature.data());
+
1247 std::unique_ptr<ECDSA_SIG,
decltype(&ECDSA_SIG_free)> sig(
+
1248 d2i_ECDSA_SIG(
nullptr, &possl_signature,
static_cast<long>(der_signature.length())),
+
+
+
1251 ec = error::signature_generation_error::signature_decoding_failed;
+
+
+
+
1255#ifdef JWT_OPENSSL_1_0_0
+
+
+
+
+
+
+
1262 ECDSA_SIG_get0(sig.get(), &r, &s);
+
+
+
+
1266 if (rr.size() > signature_length / 2 || rs.size() > signature_length / 2)
+
1267 throw std::logic_error(
"bignum size exceeded expected length");
+
1268 rr.insert(0, signature_length / 2 - rr.size(),
'\0');
+
1269 rs.insert(0, signature_length / 2 - rs.size(),
'\0');
+
+
+
+
1273 std::string p1363_to_der_signature(
const std::string& signature, std::error_code& ec)
const {
+
+
1275 auto r =
helper::raw2bn(signature.substr(0, signature.size() / 2));
+
+
+
+
1279#ifdef JWT_OPENSSL_1_0_0
+
+
+
+
+
+
1285 std::unique_ptr<ECDSA_SIG,
decltype(&ECDSA_SIG_free)> sig(ECDSA_SIG_new(), ECDSA_SIG_free);
+
+
1287 ec = error::signature_verification_error::create_context_failed;
+
+
+
1290 ECDSA_SIG_set0(sig.get(), r.release(), s.release());
+
+
+
+
1294 int length = i2d_ECDSA_SIG(psig,
nullptr);
+
+
1296 ec = error::signature_verification_error::signature_encoding_failed;
+
+
+
1299 std::string der_signature(length,
'\0');
+
1300 unsigned char* psbuffer = (
unsigned char*)der_signature.data();
+
1301 length = i2d_ECDSA_SIG(psig, &psbuffer);
+
+
1303 ec = error::signature_verification_error::signature_encoding_failed;
+
+
+
1306 der_signature.resize(length);
+
1307 return der_signature;
+
+
+
+
1313 const EVP_MD* (*md)();
+
1315 const std::string alg_name;
+
1317 const size_t signature_length;
+
+
+
1320#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
+
+
1340 eddsa(
const std::string& public_key,
const std::string& private_key,
const std::string& public_key_password,
+
1341 const std::string& private_key_password, std::string name)
+
1342 : alg_name(std::move(name)) {
+
1343 if (!private_key.empty()) {
+
+
1345 }
else if (!public_key.empty()) {
+
+
+
+
+
1356 std::string sign(
const std::string& data, std::error_code& ec)
const {
+
+
1358 auto ctx = helper::make_evp_md_ctx();
+
+
1360 ec = error::signature_generation_error::create_context_failed;
+
+
+
1363 if (!EVP_DigestSignInit(ctx.get(),
nullptr,
nullptr,
nullptr, pkey.get())) {
+
1364 ec = error::signature_generation_error::signinit_failed;
+
+
+
+
1368 size_t len = EVP_PKEY_size(pkey.get());
+
1369 std::string res(len,
'\0');
+
+
+
+
+
1374#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
+
+
1376 if (EVP_DigestSignUpdate(ctx.get(),
reinterpret_cast<const unsigned char*
>(data.data()), data.size()) !=
+
+
1378 std::cout << ERR_error_string(ERR_get_error(), NULL) << std::endl;
+
1379 ec = error::signature_generation_error::signupdate_failed;
+
+
+
1382 if (EVP_DigestSignFinal(ctx.get(),
reinterpret_cast<unsigned char*
>(&res[0]), &len) != 1) {
+
1383 ec = error::signature_generation_error::signfinal_failed;
+
+
+
+
1387 if (EVP_DigestSign(ctx.get(),
reinterpret_cast<unsigned char*
>(&res[0]), &len,
+
1388 reinterpret_cast<const unsigned char*
>(data.data()), data.size()) != 1) {
+
1389 ec = error::signature_generation_error::signfinal_failed;
+
+
+
+
+
+
+
+
+
1404 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const {
+
+
1406 auto ctx = helper::make_evp_md_ctx();
+
+
1408 ec = error::signature_verification_error::create_context_failed;
+
+
+
1411 if (!EVP_DigestVerifyInit(ctx.get(),
nullptr,
nullptr,
nullptr, pkey.get())) {
+
1412 ec = error::signature_verification_error::verifyinit_failed;
+
+
+
+
+
+
1418#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
+
1419 if (EVP_DigestVerifyUpdate(ctx.get(),
reinterpret_cast<const unsigned char*
>(data.data()),
+
1420 data.size()) != 1) {
+
1421 ec = error::signature_verification_error::verifyupdate_failed;
+
+
+
1424 if (EVP_DigestVerifyFinal(ctx.get(),
reinterpret_cast<const unsigned char*
>(signature.data()),
+
1425 signature.size()) != 1) {
+
1426 ec = error::signature_verification_error::verifyfinal_failed;
+
+
+
+
1430 auto res = EVP_DigestVerify(ctx.get(),
reinterpret_cast<const unsigned char*
>(signature.data()),
+
1431 signature.size(),
reinterpret_cast<const unsigned char*
>(data.data()),
+
+
+
1434 ec = error::signature_verification_error::verifyfinal_failed;
+
+
+
+
+
1443 std::string name()
const {
return alg_name; }
+
+
+
+
1449 const std::string alg_name;
+
+
+
+
1465 pss(
const std::string& public_key,
const std::string& private_key,
const std::string& public_key_password,
+
1466 const std::string& private_key_password,
const EVP_MD* (*md)(), std::string name)
+
1467 : md(md), alg_name(std::move(name)) {
+
1468 if (!private_key.empty()) {
+
+
1470 }
else if (!public_key.empty()) {
+
+
+
+
+
+
1482 std::string sign(
const std::string& data, std::error_code& ec)
const {
+
+
1484 auto md_ctx = helper::make_evp_md_ctx();
+
+
1486 ec = error::signature_generation_error::create_context_failed;
+
+
+
1489 EVP_PKEY_CTX* ctx =
nullptr;
+
1490 if (EVP_DigestSignInit(md_ctx.get(), &ctx, md(),
nullptr, pkey.get()) != 1) {
+
1491 ec = error::signature_generation_error::signinit_failed;
+
+
+
1494 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
+
1495 ec = error::signature_generation_error::rsa_padding_failed;
+
+
+
+
+
1500#ifndef LIBWOLFSSL_VERSION_HEX
+
1501 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
+
1502 ec = error::signature_generation_error::set_rsa_pss_saltlen_failed;
+
+
+
+
1506 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1) {
+
1507 ec = error::signature_generation_error::digestupdate_failed;
+
+
+
+
1511 size_t size = EVP_PKEY_size(pkey.get());
+
1512 std::string res(size, 0x00);
+
1513 if (EVP_DigestSignFinal(
+
+
1515 (
unsigned char*)res.data(),
+
+
1517 ec = error::signature_generation_error::signfinal_failed;
+
+
+
+
+
+
+
1530 void verify(
const std::string& data,
const std::string& signature, std::error_code& ec)
const {
+
+
+
1533 auto md_ctx = helper::make_evp_md_ctx();
+
+
1535 ec = error::signature_verification_error::create_context_failed;
+
+
+
1538 EVP_PKEY_CTX* ctx =
nullptr;
+
1539 if (EVP_DigestVerifyInit(md_ctx.get(), &ctx, md(),
nullptr, pkey.get()) != 1) {
+
1540 ec = error::signature_verification_error::verifyinit_failed;
+
+
+
1543 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
+
1544 ec = error::signature_generation_error::rsa_padding_failed;
+
+
+
+
+
1549#ifndef LIBWOLFSSL_VERSION_HEX
+
1550 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
+
1551 ec = error::signature_verification_error::set_rsa_pss_saltlen_failed;
+
+
+
+
1555 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1) {
+
1556 ec = error::signature_verification_error::verifyupdate_failed;
+
+
+
+
1560 if (EVP_DigestVerifyFinal(md_ctx.get(), (
unsigned char*)signature.data(), signature.size()) <= 0) {
+
1561 ec = error::signature_verification_error::verifyfinal_failed;
+
+
+
+
1569 std::string name()
const {
return alg_name; }
+
+
+
+
1575 const EVP_MD* (*md)();
+
1577 const std::string alg_name;
+
+
+
1583 struct hs256 :
public hmacsha {
+
1588 explicit hs256(std::string key) : hmacsha(std::move(key), EVP_sha256,
"HS256") {}
+
+
1593 struct hs384 :
public hmacsha {
+
1598 explicit hs384(std::string key) : hmacsha(std::move(key), EVP_sha384,
"HS384") {}
+
+
1603 struct hs512 :
public hmacsha {
+
1608 explicit hs512(std::string key) : hmacsha(std::move(key), EVP_sha512,
"HS512") {}
+
+
1613 struct rs256 :
public rsa {
+
1621 explicit rs256(
const std::string& public_key,
const std::string& private_key =
"",
+
1622 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1623 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
"RS256") {}
+
+
1628 struct rs384 :
public rsa {
+
1636 explicit rs384(
const std::string& public_key,
const std::string& private_key =
"",
+
1637 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1638 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
"RS384") {}
+
+
1643 struct rs512 :
public rsa {
+
1651 explicit rs512(
const std::string& public_key,
const std::string& private_key =
"",
+
1652 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1653 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
"RS512") {}
+
+
1658 struct es256 :
public ecdsa {
+
1668 explicit es256(
const std::string& public_key,
const std::string& private_key =
"",
+
1669 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1670 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
"ES256", 64) {}
+
+
1675 struct es384 :
public ecdsa {
+
1685 explicit es384(
const std::string& public_key,
const std::string& private_key =
"",
+
1686 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1687 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
"ES384", 96) {}
+
+
1692 struct es512 :
public ecdsa {
+
1702 explicit es512(
const std::string& public_key,
const std::string& private_key =
"",
+
1703 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1704 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
"ES512", 132) {}
+
+
1709 struct es256k :
public ecdsa {
+
1718 explicit es256k(
const std::string& public_key,
const std::string& private_key =
"",
+
1719 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1720 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
"ES256K", 64) {}
+
+
+
1723#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
+
1731 struct ed25519 :
public eddsa {
+
1741 explicit ed25519(
const std::string& public_key,
const std::string& private_key =
"",
+
1742 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1743 : eddsa(public_key, private_key, public_key_password, private_key_password,
"EdDSA") {}
+
+
+
1753 struct ed448 :
public eddsa {
+
1763 explicit ed448(
const std::string& public_key,
const std::string& private_key =
"",
+
1764 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1765 : eddsa(public_key, private_key, public_key_password, private_key_password,
"EdDSA") {}
+
+
+
+
1772 struct ps256 :
public pss {
+
1780 explicit ps256(
const std::string& public_key,
const std::string& private_key =
"",
+
1781 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1782 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha256,
"PS256") {}
+
+
1787 struct ps384 :
public pss {
+
1795 explicit ps384(
const std::string& public_key,
const std::string& private_key =
"",
+
1796 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1797 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha384,
"PS384") {}
+
+
1802 struct ps512 :
public pss {
+
1810 explicit ps512(
const std::string& public_key,
const std::string& private_key =
"",
+
1811 const std::string& public_key_password =
"",
const std::string& private_key_password =
"")
+
1812 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha512,
"PS512") {}
+
+
+
+
+
+
+
1825 enum class type { boolean, integer, number, string, array,
object };
+
+
+
+
+
1829#ifdef __cpp_lib_void_t
+
1830 template<
typename... Ts>
+
1831 using void_t = std::void_t<Ts...>;
+
+
+
1834 template<
typename... Ts>
+
+
+
+
+
1839 template<
typename... Ts>
+
1840 using void_t =
typename make_void<Ts...>::type;
+
+
+
1843#ifdef __cpp_lib_experimental_detect
+
1844 template<
template<
typename...>
class _Op,
typename... _Args>
+
1845 using is_detected = std::experimental::is_detected<_Op, _Args...>;
+
+
+
1848 nonesuch() =
delete;
+
1849 ~nonesuch() =
delete;
+
1850 nonesuch(nonesuch
const&) =
delete;
+
1851 nonesuch(nonesuch
const&&) =
delete;
+
1852 void operator=(nonesuch
const&) =
delete;
+
1853 void operator=(nonesuch&&) =
delete;
+
+
+
+
1857 template<
class Default,
class AlwaysVoid,
template<
class...>
class Op,
class... Args>
+
+
1859 using value = std::false_type;
+
1860 using type = Default;
+
+
+
1863 template<
class Default,
template<
class...>
class Op,
class... Args>
+
1864 struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
+
1865 using value = std::true_type;
+
1866 using type = Op<Args...>;
+
+
+
1869 template<
template<
class...>
class Op,
class... Args>
+
1870 using is_detected =
typename detector<nonesuch, void, Op, Args...>::value;
+
+
+
1873 template<
typename T,
typename Signature>
+
1874 using is_signature =
typename std::is_same<T, Signature>;
+
+
1876 template<
typename traits_type,
template<
typename...>
class Op,
typename Signature>
+
1877 struct is_function_signature_detected {
+
1878 using type = Op<traits_type>;
+
1879 static constexpr auto value = is_detected<Op, traits_type>::value && std::is_function<type>::value &&
+
1880 is_signature<type, Signature>::value;
+
+
+
1883 template<
typename traits_type,
typename value_type>
+
1884 struct supports_get_type {
+
1885 template<
typename T>
+
1886 using get_type_t =
decltype(T::get_type);
+
+
1888 static constexpr auto value =
+
1889 is_function_signature_detected<traits_type, get_type_t, json::type(
const value_type&)>::value;
+
+
+
1892 static_assert(value,
"traits implementation must provide `jwt::json::type get_type(const value_type&)`");
+
+
+
1895#define JWT_CPP_JSON_TYPE_TYPE(TYPE) json_##TYPE_type
+
1896#define JWT_CPP_AS_TYPE_T(TYPE) as_##TYPE_t
+
1897#define JWT_CPP_SUPPORTS_AS(TYPE) \
+
1898 template<typename traits_type, typename value_type, typename JWT_CPP_JSON_TYPE_TYPE(TYPE)> \
+
1899 struct supports_as_##TYPE { \
+
1900 template<typename T> \
+
1901 using JWT_CPP_AS_TYPE_T(TYPE) = decltype(T::as_##TYPE); \
+
+
1903 static constexpr auto value = \
+
1904 is_function_signature_detected<traits_type, JWT_CPP_AS_TYPE_T(TYPE), \
+
1905 JWT_CPP_JSON_TYPE_TYPE(TYPE)(const value_type&)>::value; \
+
+
1907 static_assert(value, "traits implementation must provide `" #TYPE "_type as_" #TYPE "(const value_type&)`"); \
+
+
+
1910 JWT_CPP_SUPPORTS_AS(
object);
+
1911 JWT_CPP_SUPPORTS_AS(array);
+
1912 JWT_CPP_SUPPORTS_AS(
string);
+
1913 JWT_CPP_SUPPORTS_AS(number);
+
1914 JWT_CPP_SUPPORTS_AS(integer);
+
1915 JWT_CPP_SUPPORTS_AS(
boolean);
+
+
1917#undef JWT_CPP_JSON_TYPE_TYPE
+
1918#undef JWT_CPP_AS_TYPE_T
+
1919#undef JWT_CPP_SUPPORTS_AS
+
+
1921 template<
typename traits>
+
1922 struct is_valid_traits {
+
1923 static constexpr auto value =
+
1924 supports_get_type<traits, typename traits::value_type>::value &&
+
1925 supports_as_object<traits, typename traits::value_type, typename traits::object_type>::value &&
+
1926 supports_as_array<traits, typename traits::value_type, typename traits::array_type>::value &&
+
1927 supports_as_string<traits, typename traits::value_type, typename traits::string_type>::value &&
+
1928 supports_as_number<traits, typename traits::value_type, typename traits::number_type>::value &&
+
1929 supports_as_integer<traits, typename traits::value_type, typename traits::integer_type>::value &&
+
1930 supports_as_boolean<traits, typename traits::value_type, typename traits::boolean_type>::value;
+
+
+
1933 template<
typename value_type>
+
1934 struct is_valid_json_value {
+
1935 static constexpr auto value =
+
1936 std::is_default_constructible<value_type>::value &&
+
1937 std::is_constructible<value_type, const value_type&>::value &&
+
1938 std::is_move_constructible<value_type>::value && std::is_assignable<value_type, value_type>::value &&
+
1939 std::is_copy_assignable<value_type>::value && std::is_move_assignable<value_type>::value;
+
+
+
+
+
1944 template<
typename T,
typename =
void>
+
1945 struct is_iterable : std::false_type {};
+
+
1947 template<
typename T>
+
1948 struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>())),
+
1949#if __cplusplus > 201402L
+
1950 decltype(std::cbegin(std::declval<T>())), decltype(std::cend(std::declval<T>()))
+
+
1952 decltype(std::begin(std::declval<const T>())),
+
1953 decltype(std::end(std::declval<const T>()))
+
+
1955 >> : std::true_type {
+
+
+
1958#if __cplusplus > 201703L
+
1959 template<
typename T>
+
1960 inline constexpr bool is_iterable_v = is_iterable<T>::value;
+
+
+
1963 template<
typename object_type,
typename string_type>
+
1964 using is_count_signature =
typename std::is_integral<decltype(std::declval<const object_type>().count(
+
1965 std::declval<const string_type>()))>;
+
+
1967 template<
typename object_type,
typename string_type,
typename =
void>
+
1968 struct is_subcription_operator_signature : std::false_type {};
+
+
1970 template<
typename object_type,
typename string_type>
+
1971 struct is_subcription_operator_signature<
+
1972 object_type, string_type,
+
1973 void_t<decltype(std::declval<object_type>().operator[](std::declval<string_type>()))>> : std::true_type {
+
+
+
+
1977 "object_type must implementate the subscription operator '[]' taking string_type as an argument");
+
+
+
1980 template<
typename object_type,
typename value_type,
typename string_type>
+
1981 using is_at_const_signature =
+
1982 typename std::is_same<decltype(std::declval<const object_type>().at(std::declval<const string_type>())),
+
+
+
1985 template<
typename value_type,
typename string_type,
typename object_type>
+
1986 struct is_valid_json_object {
+
1987 template<
typename T>
+
1988 using mapped_type_t =
typename T::mapped_type;
+
1989 template<
typename T>
+
1990 using key_type_t =
typename T::key_type;
+
1991 template<
typename T>
+
1992 using iterator_t =
typename T::iterator;
+
1993 template<
typename T>
+
1994 using const_iterator_t =
typename T::const_iterator;
+
+
1996 static constexpr auto value =
+
1997 std::is_constructible<value_type, object_type>::value &&
+
1998 is_detected<mapped_type_t, object_type>::value &&
+
1999 std::is_same<typename object_type::mapped_type, value_type>::value &&
+
2000 is_detected<key_type_t, object_type>::value &&
+
2001 (std::is_same<typename object_type::key_type, string_type>::value ||
+
2002 std::is_constructible<typename object_type::key_type, string_type>::value) &&
+
2003 is_detected<iterator_t, object_type>::value && is_detected<const_iterator_t, object_type>::value &&
+
2004 is_iterable<object_type>::value && is_count_signature<object_type, string_type>::value &&
+
2005 is_subcription_operator_signature<object_type, string_type>::value &&
+
2006 is_at_const_signature<object_type, value_type, string_type>::value;
+
+
+
2009 template<
typename value_type,
typename array_type>
+
2010 struct is_valid_json_array {
+
2011 template<
typename T>
+
2012 using value_type_t =
typename T::value_type;
+
+
2014 static constexpr auto value = std::is_constructible<value_type, array_type>::value &&
+
2015 is_iterable<array_type>::value &&
+
2016 is_detected<value_type_t, array_type>::value &&
+
2017 std::is_same<typename array_type::value_type, value_type>::value;
+
+
+
2020 template<
typename string_type,
typename integer_type>
+
2021 using is_substr_start_end_index_signature =
+
2022 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>(),
+
2023 std::declval<integer_type>())),
+
+
+
2026 template<
typename string_type,
typename integer_type>
+
2027 using is_substr_start_index_signature =
+
2028 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>())),
+
+
+
2031 template<
typename string_type>
+
2032 using is_std_operate_plus_signature =
+
2033 typename std::is_same<decltype(std::operator+(std::declval<string_type>(), std::declval<string_type>())),
+
+
+
2036 template<
typename value_type,
typename string_type,
typename integer_type>
+
2037 struct is_valid_json_string {
+
2038 static constexpr auto substr = is_substr_start_end_index_signature<string_type, integer_type>::value &&
+
2039 is_substr_start_index_signature<string_type, integer_type>::value;
+
2040 static_assert(substr,
"string_type must have a substr method taking only a start index and an overload "
+
2041 "taking a start and end index, both must return a string_type");
+
+
2043 static constexpr auto operator_plus = is_std_operate_plus_signature<string_type>::value;
+
2044 static_assert(operator_plus,
+
2045 "string_type must have a '+' operator implemented which returns the concatenated string");
+
+
2047 static constexpr auto value =
+
2048 std::is_constructible<value_type, string_type>::value && substr && operator_plus;
+
+
+
2051 template<
typename value_type,
typename number_type>
+
2052 struct is_valid_json_number {
+
2053 static constexpr auto value =
+
2054 std::is_floating_point<number_type>::value && std::is_constructible<value_type, number_type>::value;
+
+
+
2057 template<
typename value_type,
typename integer_type>
+
2058 struct is_valid_json_integer {
+
2059 static constexpr auto value = std::is_signed<integer_type>::value &&
+
2060 !std::is_floating_point<integer_type>::value &&
+
2061 std::is_constructible<value_type, integer_type>::value;
+
+
2063 template<
typename value_type,
typename boolean_type>
+
2064 struct is_valid_json_boolean {
+
2065 static constexpr auto value = std::is_convertible<boolean_type, bool>::value &&
+
2066 std::is_constructible<value_type, boolean_type>::value;
+
+
+
2069 template<
typename value_type,
typename object_type,
typename array_type,
typename string_type,
+
2070 typename number_type,
typename integer_type,
typename boolean_type>
+
2071 struct is_valid_json_types {
+
+
2073 static_assert(is_valid_json_value<value_type>::value,
+
2074 "value_type must meet basic requirements, default constructor, copyable, moveable");
+
2075 static_assert(is_valid_json_object<value_type, string_type, object_type>::value,
+
2076 "object_type must be a string_type to value_type container");
+
2077 static_assert(is_valid_json_array<value_type, array_type>::value,
+
2078 "array_type must be a container of value_type");
+
+
2080 static constexpr auto value = is_valid_json_value<value_type>::value &&
+
2081 is_valid_json_object<value_type, string_type, object_type>::value &&
+
2082 is_valid_json_array<value_type, array_type>::value &&
+
2083 is_valid_json_string<value_type, string_type, integer_type>::value &&
+
2084 is_valid_json_number<value_type, number_type>::value &&
+
2085 is_valid_json_integer<value_type, integer_type>::value &&
+
2086 is_valid_json_boolean<value_type, boolean_type>::value;
+
+
+
+
2097 template<
typename json_traits>
+
+
+
2105 static_assert(std::is_same<typename json_traits::string_type, std::string>::value ||
+
2106 std::is_convertible<typename json_traits::string_type, std::string>::value ||
+
2107 std::is_constructible<typename json_traits::string_type, std::string>::value,
+
2108 "string_type must be a std::string, convertible to a std::string, or construct a std::string.");
+
+
+
2111 details::is_valid_json_types<
typename json_traits::value_type,
typename json_traits::object_type,
+
2112 typename json_traits::array_type,
typename json_traits::string_type,
+
2113 typename json_traits::number_type,
typename json_traits::integer_type,
+
2114 typename json_traits::boolean_type>::value,
+
2115 "must staisfy json container requirements");
+
2116 static_assert(details::is_valid_traits<json_traits>::value,
"traits must satisfy requirements");
+
+
2118 typename json_traits::value_type val;
+
+
+
2121 using set_t = std::set<typename json_traits::string_type>;
+
+
+
+
+
+
+
+
+
2130 JWT_CLAIM_EXPLICIT
basic_claim(
typename json_traits::string_type s) : val(std::move(s)) {}
+
+
2132 : val(
typename json_traits::integer_type(std::chrono::system_clock::to_time_t(d))) {}
+
2133 JWT_CLAIM_EXPLICIT
basic_claim(
typename json_traits::array_type a) : val(std::move(a)) {}
+
2134 JWT_CLAIM_EXPLICIT
basic_claim(
typename json_traits::value_type v) : val(std::move(v)) {}
+
2135 JWT_CLAIM_EXPLICIT
basic_claim(
const set_t& s) : val(
typename json_traits::array_type(s.begin(), s.end())) {}
+
2136 template<
typename Iterator>
+
2137 basic_claim(Iterator begin, Iterator end) : val(
typename json_traits::array_type(begin, end)) {}
+
+
2143 typename json_traits::value_type
to_json()
const {
return val; }
+
+
+
+
+
+
2162 json::type
get_type()
const {
return json_traits::get_type(val); }
+
+
2169 typename json_traits::string_type
as_string()
const {
return json_traits::as_string(val); }
+
+
+
+
2180 using std::chrono::system_clock;
+
2181 if (
get_type() == json::type::number)
return system_clock::from_time_t(std::round(
as_number()));
+
2182 return system_clock::from_time_t(
as_integer());
+
+
+
+
2190 typename json_traits::array_type
as_array()
const {
return json_traits::as_array(val); }
+
+
+
+
+
2199 for (
const auto& e : json_traits::as_array(val)) {
+
2200 res.insert(json_traits::as_string(e));
+
+
+
+
+
+
2210 typename json_traits::integer_type
as_integer()
const {
return json_traits::as_integer(val); }
+
+
2217 typename json_traits::boolean_type
as_boolean()
const {
return json_traits::as_boolean(val); }
+
+
2224 typename json_traits::number_type
as_number()
const {
return json_traits::as_number(val); }
+
+
+
+
+
+
+
+
+
+
2243 template<
typename json_traits>
+
2244 struct map_of_claims {
+
2245 typename json_traits::object_type claims;
+
+
2247 using iterator =
typename json_traits::object_type::iterator;
+
2248 using const_iterator =
typename json_traits::object_type::const_iterator;
+
+
2250 map_of_claims() =
default;
+
2251 map_of_claims(
const map_of_claims&) =
default;
+
2252 map_of_claims(map_of_claims&&) =
default;
+
2253 map_of_claims& operator=(
const map_of_claims&) =
default;
+
2254 map_of_claims& operator=(map_of_claims&&) =
default;
+
+
2256 map_of_claims(
typename json_traits::object_type json) : claims(std::move(json)) {}
+
+
2258 iterator begin() {
return claims.begin(); }
+
2259 iterator end() {
return claims.end(); }
+
2260 const_iterator cbegin()
const {
return claims.begin(); }
+
2261 const_iterator cend()
const {
return claims.end(); }
+
2262 const_iterator begin()
const {
return claims.begin(); }
+
2263 const_iterator end()
const {
return claims.end(); }
+
+
2273 static typename json_traits::object_type parse_claims(
const typename json_traits::string_type& str) {
+
2274 typename json_traits::value_type val;
+
2275 if (!json_traits::parse(val, str))
throw error::invalid_json_exception();
+
+
2277 return json_traits::as_object(val);
+
+
+
2284 bool has_claim(
const typename json_traits::string_type& name)
const noexcept {
+
2285 return claims.count(name) != 0;
+
+
+
2295 basic_claim_t get_claim(
const typename json_traits::string_type& name)
const {
+
2296 if (!has_claim(name))
throw error::claim_not_present_exception();
+
2297 return basic_claim_t{claims.at(name)};
+
+
+
+
+
2306 template<
typename json_traits>
+
+
+
+
2309 details::map_of_claims<json_traits> payload_claims;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2371 if (aud.get_type() == json::type::string)
return {aud.as_string()};
+
+
2373 return aud.as_set();
+
+
+
+
+
+
+
+
+
2408 return payload_claims.has_claim(name);
+
+
+
+
+
2416 return payload_claims.get_claim(name);
+
+
+
+
+
+
2424 template<
typename json_traits>
+
+
+
+
2427 details::map_of_claims<json_traits> header_claims;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2484 return header_claims.has_claim(name);
+
+
+
+
+
2492 return header_claims.get_claim(name);
+
+
+
+
+
+
2499 template<
typename json_traits>
+
+
+
+
2503 typename json_traits::string_type
token;
+
+
+
+
+
+
+
+
+
+
2519#ifndef JWT_DISABLE_BASE64
+
+
+
+
2531 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(str));
+
+
+
+
2545 template<
typename Decode>
+
+
+
2547 auto hdr_end =
token.find(
'.');
+
2548 if (hdr_end == json_traits::string_type::npos)
throw std::invalid_argument(
"invalid token supplied");
+
2549 auto payload_end =
token.find(
'.', hdr_end + 1);
+
2550 if (payload_end == json_traits::string_type::npos)
throw std::invalid_argument(
"invalid token supplied");
+
+
+
+
+
+
+
+
+
2559 this->header_claims = details::map_of_claims<json_traits>::parse_claims(
header);
+
2560 this->payload_claims = details::map_of_claims<json_traits>::parse_claims(
payload);
+
+
+
+
2567 const typename json_traits::string_type&
get_token() const noexcept {
return token; }
+
+
+
+
+
+
+
2602 typename json_traits::object_type
get_payload_json()
const {
return this->payload_claims.claims; }
+
2607 typename json_traits::object_type
get_header_json()
const {
return this->header_claims.claims; }
+
+
+
2616 return this->payload_claims.get_claim(name);
+
+
+
+
+
2626 return this->header_claims.get_claim(name);
+
+
+
+
+
+
2634 template<
typename json_traits>
+
+
+
2636 typename json_traits::object_type header_claims;
+
2637 typename json_traits::object_type payload_claims;
+
+
+
+
+
+
2648 header_claims[id] = std::move(c);
+
+
+
+
+
+
+
2659 header_claims[id] = c.
to_json();
+
+
+
+
+
+
2669 payload_claims[id] = std::move(c);
+
+
+
+
+
+
2679 payload_claims[id] = c.
to_json();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2787 template<
typename Algo,
typename Encode>
+
+
2788 typename json_traits::string_type
sign(
const Algo& algo, Encode encode)
const {
+
+
2790 auto res =
sign(algo, encode, ec);
+
2791 error::throw_if_error(ec);
+
+
+
+
2794#ifndef JWT_DISABLE_BASE64
+
2803 template<
typename Algo>
+
+
2804 typename json_traits::string_type
sign(
const Algo& algo)
const {
+
+
2806 auto res =
sign(algo, ec);
+
2807 error::throw_if_error(ec);
+
+
+
+
+
+
2824 template<
typename Algo,
typename Encode>
+
+
2825 typename json_traits::string_type
sign(
const Algo& algo, Encode encode, std::error_code& ec)
const {
+
+
2827 typename json_traits::object_type obj_header = header_claims;
+
2828 if (header_claims.count(
"alg") == 0) obj_header[
"alg"] =
typename json_traits::value_type(algo.name());
+
+
2830 const auto header = encode(json_traits::serialize(
typename json_traits::value_type(obj_header)));
+
2831 const auto payload = encode(json_traits::serialize(
typename json_traits::value_type(payload_claims)));
+
+
+
2834 auto signature = algo.sign(token, ec);
+
+
+
2837 return token +
"." + encode(signature);
+
+
+
2839#ifndef JWT_DISABLE_BASE64
+
2849 template<
typename Algo>
+
+
2850 typename json_traits::string_type
sign(
const Algo& algo, std::error_code& ec)
const {
+
+
+
2853 [](
const typename json_traits::string_type& data) {
+
2854 return base::trim<alphabet::base64url>(base::encode<alphabet::base64url>(data));
+
+
+
+
+
+
+
+
+
2861 namespace verify_ops {
+
2865 template<
typename json_traits>
+
+
+
+
2868 : current_time(ctime),
jwt(j), default_leeway(l) {}
+
+
+
+
+
+
2874 size_t default_leeway{0};
+
+
+
2877 typename json_traits::string_type claim_key{};
+
+
+
+
+
2882 if (!
jwt.has_header_claim(claim_key)) {
+
2883 ec = error::token_verification_error::missing_claim;
+
+
+
2886 return jwt.get_header_claim(claim_key);
+
+
2888 if (!
jwt.has_payload_claim(claim_key)) {
+
2889 ec = error::token_verification_error::missing_claim;
+
+
+
2892 return jwt.get_payload_claim(claim_key);
+
+
+
+
2896 auto c = get_claim(in_header, ec);
+
+
2898 if (c.get_type() != t) {
+
2899 ec = error::token_verification_error::claim_type_missmatch;
+
+
+
+
+
+
+
2906 return get_claim(
false, t, ec);
+
+
+
+
+
2913 template<
typename json_traits,
bool in_header = false>
+
+
+
+
+
2917 auto jc = ctx.get_claim(in_header, expected.
get_type(), ec);
+
+
2919 const bool matches = [&]() {
+
+
2921 case json::type::boolean:
return expected.
as_boolean() == jc.as_boolean();
+
2922 case json::type::integer:
return expected.
as_integer() == jc.as_integer();
+
2923 case json::type::number:
return expected.
as_number() == jc.as_number();
+
2924 case json::type::string:
return expected.
as_string() == jc.as_string();
+
2925 case json::type::array:
+
2926 case json::type::object:
+
2927 return json_traits::serialize(expected.
to_json()) == json_traits::serialize(jc.to_json());
+
2928 default:
throw std::logic_error(
"internal error, should be unreachable");
+
+
+
+
2932 ec = error::token_verification_error::claim_value_missmatch;
+
+
+
+
+
+
+
2942 template<
typename json_traits,
bool in_header = false>
+
+
+
2944 const size_t leeway;
+
+
2946 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
+
+
2948 auto c = jc.as_date();
+
2949 if (ctx.current_time > c + std::chrono::seconds(leeway)) {
+
2950 ec = error::token_verification_error::token_expired;
+
+
+
+
+
+
2959 template<
typename json_traits,
bool in_header = false>
+
+
+
2961 const size_t leeway;
+
+
2963 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
+
+
2965 auto c = jc.as_date();
+
2966 if (ctx.current_time < c - std::chrono::seconds(leeway)) {
+
2967 ec = error::token_verification_error::token_expired;
+
+
+
+
+
+
2977 template<
typename json_traits,
bool in_header = false>
+
+
+
2979 const typename basic_claim<json_traits>::set_t expected;
+
+
2981 auto c = ctx.get_claim(in_header, ec);
+
+
2983 if (c.get_type() == json::type::string) {
+
2984 if (expected.size() != 1 || *expected.begin() != c.
as_string()) {
+
2985 ec = error::token_verification_error::audience_missmatch;
+
+
+
2988 }
else if (c.get_type() == json::type::array) {
+
2989 auto jc = c.as_set();
+
2990 for (
auto& e : expected) {
+
2991 if (jc.find(e) == jc.end()) {
+
2992 ec = error::token_verification_error::audience_missmatch;
+
+
+
+
+
2997 ec = error::token_verification_error::claim_type_missmatch;
+
+
+
+
+
+
+
3006 template<
typename json_traits,
bool in_header = false>
+
+
+
3008 const typename json_traits::string_type expected;
+
+
+
3011 : expected(to_lower_unicode(e, loc)), locale(loc) {}
+
+
+
3014 const auto c = ctx.get_claim(in_header, json::type::string, ec);
+
+
3016 if (to_lower_unicode(c.as_string(), locale) != expected) {
+
3017 ec = error::token_verification_error::claim_value_missmatch;
+
+
+
+
3021 static std::string to_lower_unicode(
const std::string& str,
const std::locale& loc) {
+
3022 std::mbstate_t state = std::mbstate_t();
+
3023 const char* in_next = str.data();
+
3024 const char* in_end = str.data() + str.size();
+
+
3026 wide.reserve(str.size());
+
+
3028 while (in_next != in_end) {
+
+
3030 std::size_t result = std::mbrtowc(&wc, in_next, in_end - in_next, &state);
+
3031 if (result ==
static_cast<std::size_t
>(-1)) {
+
3032 throw std::runtime_error(
"encoding error: " + std::string(std::strerror(errno)));
+
3033 }
else if (result ==
static_cast<std::size_t
>(-2)) {
+
3034 throw std::runtime_error(
"conversion error: next bytes constitute an incomplete, but so far "
+
3035 "valid, multibyte character.");
+
+
+
+
+
+
3041 auto& f = std::use_facet<std::ctype<wchar_t>>(loc);
+
3042 f.tolower(&wide[0], &wide[0] + wide.size());
+
+
+
3045 out.reserve(wide.size());
+
3046 for (
wchar_t wc : wide) {
+
3047 char mb[MB_LEN_MAX];
+
3048 std::size_t n = std::wcrtomb(mb, wc, &state);
+
3049 if (n !=
static_cast<std::size_t
>(-1)) out.append(mb, n);
+
+
+
+
+
+
+
+
+
3061 template<
typename Clock,
typename json_traits>
+
+
+
+
+
+
+
+
+
+
3079 virtual ~algo_base() =
default;
+
3080 virtual void verify(
const std::string& data,
const std::string& sig, std::error_code& ec) = 0;
+
+
3082 template<
typename T>
+
3083 struct algo :
public algo_base {
+
+
3085 explicit algo(T a) : alg(a) {}
+
3086 void verify(
const std::string& data,
const std::string& sig, std::error_code& ec)
override {
+
3087 alg.verify(data, sig, ec);
+
+
+
3091 std::unordered_map<typename json_traits::string_type, verify_check_fn_t> claims;
+
3093 size_t default_leeway = 0;
+
+
3097 std::unordered_map<std::string, std::shared_ptr<algo_base>> algs;
+
+
+
+
+
+
3106 if (!ctx.jwt.has_expires_at())
return;
+
3107 auto exp = ctx.jwt.get_expires_at();
+
3108 if (ctx.current_time > exp + std::chrono::seconds(ctx.default_leeway)) {
+
3109 ec = error::token_verification_error::token_expired;
+
+
+
+
3113 if (!ctx.jwt.has_issued_at())
return;
+
3114 auto iat = ctx.jwt.get_issued_at();
+
3115 if (ctx.current_time < iat - std::chrono::seconds(ctx.default_leeway)) {
+
3116 ec = error::token_verification_error::token_expired;
+
+
+
+
3120 if (!ctx.jwt.has_not_before())
return;
+
3121 auto nbf = ctx.jwt.get_not_before();
+
3122 if (ctx.current_time < nbf - std::chrono::seconds(ctx.default_leeway)) {
+
3123 ec = error::token_verification_error::token_expired;
+
+
+
+
+
+
+
+
+
+
+
+
3179 verifier&
with_type(
const typename json_traits::string_type& type, std::locale locale = std::locale{}) {
+
+
+
+
+
+
+
+
+
+
+
3219 typename basic_claim_t::set_t s;
+
+
+
+
+
+
+
+
+
+
+
3257 template<
typename Algorithm>
+
+
+
3259 algs[alg.name()] = std::make_shared<algo<Algorithm>>(alg);
+
+
+
+
+
+
+
+
+
3271 error::throw_if_error(ec);
+
+
+
+
+
+
3280 const typename json_traits::string_type data =
jwt.get_header_base64() +
"." +
jwt.get_payload_base64();
+
3281 const typename json_traits::string_type sig =
jwt.get_signature();
+
3282 const std::string algo =
jwt.get_algorithm();
+
3283 if (algs.count(algo) == 0) {
+
3284 ec = error::token_verification_error::wrong_algorithm;
+
+
+
3287 algs.at(algo)->verify(data, sig, ec);
+
+
+
+
3291 for (
auto& c : claims) {
+
3292 ctx.claim_key = c.first;
+
+
+
+
+
+
+
+
+
3307 template<
typename json_traits>
+
+
+
+
3310 const details::map_of_claims<json_traits> jwk_claims;
+
+
+
3313 JWT_CLAIM_EXPLICIT
jwk(
const typename json_traits::string_type& str)
+
3314 : jwk_claims(details::map_of_claims<json_traits>::parse_claims(str)) {}
+
+
3316 JWT_CLAIM_EXPLICIT
jwk(
const typename json_traits::value_type& json)
+
3317 : jwk_claims(json_traits::as_object(json)) {}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
3415 return json_traits::as_string(x5c_array.front());
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
3482 bool has_jwk_claim(
const typename json_traits::string_type& name)
const noexcept {
+
3483 return jwk_claims.has_claim(name);
+
+
+
+
+
+
3492 return jwk_claims.get_claim(name);
+
+
+
+
3495 bool empty() const noexcept {
return jwk_claims.empty(); }
+
+
3501 typename json_traits::object_type
get_claims()
const {
return this->jwk_claims.claims; }
+
+
+
+
3514 template<
typename json_traits>
+
+
+
+
+
3518 using jwt_vector_t = std::vector<jwk_t>;
+
3519 using iterator =
typename jwt_vector_t::iterator;
+
3520 using const_iterator =
typename jwt_vector_t::const_iterator;
+
+
3522 JWT_CLAIM_EXPLICIT
jwks(
const typename json_traits::string_type& str) {
+
3523 typename json_traits::value_type parsed_val;
+
+
+
3526 const details::map_of_claims<json_traits> jwks_json = json_traits::as_object(parsed_val);
+
+
+
3529 auto jwk_list = jwks_json.get_claim(
"keys").as_array();
+
3530 std::transform(jwk_list.begin(), jwk_list.end(), std::back_inserter(jwk_claims),
+
3531 [](
const typename json_traits::value_type& val) { return jwk_t{val}; });
+
+
+
3534 iterator begin() {
return jwk_claims.begin(); }
+
3535 iterator end() {
return jwk_claims.end(); }
+
3536 const_iterator cbegin()
const {
return jwk_claims.begin(); }
+
3537 const_iterator cend()
const {
return jwk_claims.end(); }
+
3538 const_iterator begin()
const {
return jwk_claims.begin(); }
+
3539 const_iterator end()
const {
return jwk_claims.end(); }
+
+
+
3545 bool has_jwk(
const typename json_traits::string_type& key_id)
const noexcept {
+
3546 return find_by_kid(key_id) != end();
+
+
+
+
+
+
3555 const auto maybe = find_by_kid(key_id);
+
+
+
+
+
+
+
3561 jwt_vector_t jwk_claims;
+
+
3563 const_iterator find_by_kid(
const typename json_traits::string_type& key_id)
const noexcept {
+
3564 return std::find_if(cbegin(), cend(), [key_id](
const jwk_t&
jwk) {
+
+
+
+
+
+
+
+
3576 template<
typename Clock,
typename json_traits>
+
+
+
+
+
3585 date now()
const {
return date::clock::now(); }
+
+
+
+
3593 template<
typename json_traits>
+
+
+
3595 return verifier<default_clock, json_traits>(c);
+
+
+
+
3601 template<
typename json_traits>
+
+
+
3614 template<
typename json_traits,
typename Decode>
+
+
+
3627 template<
typename json_traits>
+
+
3637 template<
typename json_traits>
+
+
3647 template<
typename json_traits>
+
+
+
+
3653template<
typename json_traits>
+
+
3655 return c.operator>>(is);
+
+
+
3658template<
typename json_traits>
+
+
+
+
+
3663#ifndef JWT_DISABLE_PICOJSON
+
3664#include "traits/kazuho-picojson/defaults.h"
+
+
+
+
a class to store a generic JSON value as claim
Definition jwt.h:2098
+
json_traits::number_type as_number() const
Get the contained JSON value as a number.
Definition jwt.h:2224
+
set_t as_set() const
Get the contained JSON value as a set of strings.
Definition jwt.h:2197
+
json::type get_type() const
Get type of contained JSON value.
Definition jwt.h:2162
+
std::istream & operator>>(std::istream &is)
Parse input stream into underlying JSON value.
Definition jwt.h:2149
+
json_traits::boolean_type as_boolean() const
Get the contained JSON value as a bool.
Definition jwt.h:2217
+
date as_date() const
Get the contained JSON value as a date.
Definition jwt.h:2179
+
std::ostream & operator<<(std::ostream &os)
Serialize claim to output stream from wrapped JSON value.
Definition jwt.h:2155
+
json_traits::integer_type as_integer() const
Get the contained JSON value as an integer.
Definition jwt.h:2210
+
json_traits::value_type to_json() const
Get wrapped JSON value.
Definition jwt.h:2143
+
json_traits::array_type as_array() const
Get the contained JSON value as an array.
Definition jwt.h:2190
+
json_traits::string_type as_string() const
Get the contained JSON value as a string.
Definition jwt.h:2169
+
Builder class to build and sign a new token Use jwt::create() to get an instance of this class.
Definition jwt.h:2635
+
builder & set_payload_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Set a payload claim.
Definition jwt.h:2668
+
json_traits::string_type sign(const Algo &algo) const
Sign token and return result.
Definition jwt.h:2804
+
json_traits::string_type sign(const Algo &algo, Encode encode) const
Sign token and return result.
Definition jwt.h:2788
+
builder & set_audience(typename json_traits::string_type aud)
Set audience claim.
Definition jwt.h:2746
+
builder & set_audience(typename json_traits::array_type a)
Set audience claim.
Definition jwt.h:2738
+
builder & set_header_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Set a header claim.
Definition jwt.h:2658
+
builder & set_payload_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Set a payload claim.
Definition jwt.h:2678
+
builder & set_subject(typename json_traits::string_type str)
Set subject claim.
Definition jwt.h:2730
+
builder & set_content_type(typename json_traits::string_type str)
Set content type claim.
Definition jwt.h:2705
+
builder & set_not_before(const date &d)
Set not before claim.
Definition jwt.h:2760
+
builder & set_issued_at(const date &d)
Set issued at claim.
Definition jwt.h:2766
+
builder & set_id(const typename json_traits::string_type &str)
Set id claim.
Definition jwt.h:2772
+
builder & set_type(typename json_traits::string_type str)
Set type claim.
Definition jwt.h:2697
+
builder & set_key_id(typename json_traits::string_type str)
Set key id claim.
Definition jwt.h:2714
+
builder & set_issuer(typename json_traits::string_type str)
Set issuer claim.
Definition jwt.h:2722
+
builder & set_header_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Set a header claim.
Definition jwt.h:2647
+
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:2689
+
json_traits::string_type sign(const Algo &algo, std::error_code &ec) const
Sign token and return result.
Definition jwt.h:2850
+
builder & set_expires_at(const date &d)
Set expires at claim.
Definition jwt.h:2754
+
json_traits::string_type sign(const Algo &algo, Encode encode, std::error_code &ec) const
Sign token and return result.
Definition jwt.h:2825
+
Class containing all information about a decoded token.
Definition jwt.h:2500
+
const json_traits::string_type & get_header() const noexcept
Get header part as json string.
Definition jwt.h:2572
+
const json_traits::string_type & get_signature_base64() const noexcept
Get signature part as base64 string.
Definition jwt.h:2597
+
json_traits::string_type signature
Signature part decoded from base64.
Definition jwt.h:2513
+
json_traits::string_type header
Header part decoded from base64.
Definition jwt.h:2505
+
json_traits::string_type header_base64
Unmodified header part in base64.
Definition jwt.h:2507
+
json_traits::string_type token
Unmodified token, as passed to constructor.
Definition jwt.h:2503
+
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Get a payload claim by name.
Definition jwt.h:2615
+
const json_traits::string_type & get_signature() const noexcept
Get signature part as json string.
Definition jwt.h:2582
+
JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type &token)
Parses a given token.
Definition jwt.h:2529
+
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Get a header claim by name.
Definition jwt.h:2625
+
decoded_jwt(const typename json_traits::string_type &token, Decode decode)
Parses a given token.
Definition jwt.h:2546
+
json_traits::object_type get_payload_json() const
Get all payload as JSON object.
Definition jwt.h:2602
+
json_traits::string_type signature_base64
Unmodified signature part in base64.
Definition jwt.h:2515
+
const json_traits::string_type & get_payload_base64() const noexcept
Get payload part as base64 string.
Definition jwt.h:2592
+
const json_traits::string_type & get_token() const noexcept
Get token string, as passed to constructor.
Definition jwt.h:2567
+
json_traits::object_type get_header_json() const
Get all header as JSON object.
Definition jwt.h:2607
+
const json_traits::string_type & get_payload() const noexcept
Get payload part as json string.
Definition jwt.h:2577
+
const json_traits::string_type & get_header_base64() const noexcept
Get header part as base64 string.
Definition jwt.h:2587
+
json_traits::string_type payload_base64
Unmodified payload part in base64.
Definition jwt.h:2511
+
json_traits::string_type payload
Payload part decoded from base64.
Definition jwt.h:2509
+
+
+
+
+
+
+
+
+
+
+
+
Handle class for EVP_PKEY structures.
Definition jwt.h:398
+
constexpr evp_pkey_handle(EVP_PKEY *key) noexcept
Construct a new handle.
Definition jwt.h:419
+
JSON Web Key.
Definition jwt.h:3308
+
bool has_x5c() const noexcept
Check if X509 Chain is present ("x5c")
Definition jwt.h:3464
+
json_traits::string_type get_curve() const
Get curve claim.
Definition jwt.h:3371
+
bool has_x5t_sha256() const noexcept
Check if a X509 SHA256 thumbprint is present ("x5t#S256")
Definition jwt.h:3476
+
json_traits::string_type get_algorithm() const
Get algorithm claim.
Definition jwt.h:3351
+
json_traits::array_type get_x5c() const
Get x5c claim.
Definition jwt.h:3379
+
json_traits::object_type get_claims() const
Get all jwk claims.
Definition jwt.h:3501
+
json_traits::string_type get_x5t() const
Get X509 thumbprint claim.
Definition jwt.h:3395
+
json_traits::string_type get_x5c_key_value() const
Get x5c claim as a string.
Definition jwt.h:3411
+
json_traits::string_type get_x5t_sha256() const
Get X509 SHA256 thumbprint claim.
Definition jwt.h:3403
+
json_traits::string_type get_key_id() const
Get key id claim.
Definition jwt.h:3359
+
bool has_algorithm() const noexcept
Check if algorithm is present ("alg")
Definition jwt.h:3440
+
json_traits::string_type get_use() const
Get public key usage claim.
Definition jwt.h:3335
+
bool has_key_id() const noexcept
Check if key id is present ("kid")
Definition jwt.h:3452
+
bool has_x5u() const noexcept
Check if X509 URL is present ("x5u")
Definition jwt.h:3458
+
bool has_key_operations() const noexcept
Check if a key operations parameter is present ("key_ops")
Definition jwt.h:3434
+
bool has_use() const noexcept
Check if a public key usage indication is present ("use")
Definition jwt.h:3428
+
bool has_x5t() const noexcept
Check if a X509 thumbprint is present ("x5t")
Definition jwt.h:3470
+
bool has_jwk_claim(const typename json_traits::string_type &name) const noexcept
Check if a jwks claim is present.
Definition jwt.h:3482
+
basic_claim_t::set_t get_key_operations() const
Get key operation types claim.
Definition jwt.h:3343
+
bool has_curve() const noexcept
Check if curve is present ("crv")
Definition jwt.h:3446
+
bool has_key_type() const noexcept
Check if a key type is present ("kty")
Definition jwt.h:3422
+
basic_claim_t get_jwk_claim(const typename json_traits::string_type &name) const
Get jwks claim.
Definition jwt.h:3491
+
json_traits::string_type get_x5u() const
Get X509 URL claim.
Definition jwt.h:3387
+
json_traits::string_type get_key_type() const
Get key type claim.
Definition jwt.h:3327
+
JWK Set.
Definition jwt.h:3515
+
jwk_t get_jwk(const typename json_traits::string_type &key_id) const
Get jwk.
Definition jwt.h:3554
+
bool has_jwk(const typename json_traits::string_type &key_id) const noexcept
Check if a jwk with the kid is present.
Definition jwt.h:3545
+
Base class that represents a token payload.
Definition jwt.h:2307
+
basic_claim_t::set_t get_audience() const
Get audience claim.
Definition jwt.h:2369
+
json_traits::string_type get_id() const
Get id claim.
Definition jwt.h:2402
+
bool has_issued_at() const noexcept
Check if issued at is present ("iat")
Definition jwt.h:2343
+
bool has_not_before() const noexcept
Check if not before is present ("nbf")
Definition jwt.h:2338
+
bool has_payload_claim(const typename json_traits::string_type &name) const noexcept
Check if a payload claim is present.
Definition jwt.h:2407
+
bool has_subject() const noexcept
Check if subject is present ("sub")
Definition jwt.h:2323
+
date get_not_before() const
Get not valid before claim.
Definition jwt.h:2388
+
bool has_issuer() const noexcept
Check if issuer is present ("iss")
Definition jwt.h:2318
+
bool has_id() const noexcept
Check if token id is present ("jti")
Definition jwt.h:2348
+
bool has_expires_at() const noexcept
Check if expires is present ("exp")
Definition jwt.h:2333
+
date get_issued_at() const
Get issued at claim.
Definition jwt.h:2395
+
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Get payload claim.
Definition jwt.h:2415
+
bool has_audience() const noexcept
Check if audience is present ("aud")
Definition jwt.h:2328
+
date get_expires_at() const
Get expires claim.
Definition jwt.h:2381
+
json_traits::string_type get_subject() const
Get subject claim.
Definition jwt.h:2362
+
json_traits::string_type get_issuer() const
Get issuer claim.
Definition jwt.h:2355
+
Verifier class used to check if a decoded token contains all claims required by your application and ...
Definition jwt.h:3062
+
verifier & expires_at_leeway(size_t leeway)
Set leeway for expires at.
Definition jwt.h:3143
+
std::function< void(const verify_ops::verify_context< json_traits > &, std::error_code &ec)> verify_check_fn_t
Verification function.
Definition jwt.h:3075
+
verifier & with_claim(const typename json_traits::string_type &name, verify_check_fn_t fn)
Specify a claim to check for using the specified operation.
Definition jwt.h:3237
+
void verify(const decoded_jwt< json_traits > &jwt, std::error_code &ec) const
Verify the given token.
Definition jwt.h:3278
+
verifier & not_before_leeway(size_t leeway)
Set leeway for not before.
Definition jwt.h:3153
+
verifier & issued_at_leeway(size_t leeway)
Set leeway for issued at.
Definition jwt.h:3163
+
verifier & with_subject(const typename json_traits::string_type &sub)
Set a subject to check for.
Definition jwt.h:3199
+
verifier & with_audience(const typename basic_claim_t::set_t &aud)
Set an audience to check for.
Definition jwt.h:3208
+
verifier & with_claim(const typename json_traits::string_type &name, basic_claim_t c)
Specify a claim to check for equality (both type & value).
Definition jwt.h:3248
+
verifier & with_audience(const typename json_traits::string_type &aud)
Set an audience to check for.
Definition jwt.h:3218
+
void verify(const decoded_jwt< json_traits > &jwt) const
Verify the given token.
Definition jwt.h:3268
+
verifier(Clock c)
Constructor for building a new verifier instance.
Definition jwt.h:3104
+
verifier & leeway(size_t leeway)
Set default leeway to use.
Definition jwt.h:3133
+
verifier & with_issuer(const typename json_traits::string_type &iss)
Set an issuer to check for.
Definition jwt.h:3189
+
verifier & allow_algorithm(Algorithm alg)
Add an algorithm available for checking.
Definition jwt.h:3258
+
verifier & with_type(const typename json_traits::string_type &type, std::locale locale=std::locale{})
Set an type to check for.
Definition jwt.h:3179
+
verifier & with_id(const typename json_traits::string_type &id)
Set an id to check for.
Definition jwt.h:3229
+
signature_verification_error
Errors related to verification of signatures.
Definition jwt.h:197
+
std::error_category & token_verification_error_category()
Error category for token verification errors.
Definition jwt.h:328
+
std::error_category & ecdsa_error_category()
Error category for ECDSA errors.
Definition jwt.h:169
+
std::error_category & signature_verification_error_category()
Error category for verification errors.
Definition jwt.h:211
+
std::error_category & rsa_error_category()
Error category for RSA errors.
Definition jwt.h:128
+
std::error_category & signature_generation_error_category()
Error category for signature generation errors.
Definition jwt.h:268
+
ecdsa_error
Errors related to processing of RSA signatures.
Definition jwt.h:156
+
rsa_error
Errors related to processing of RSA signatures.
Definition jwt.h:113
+
signature_generation_error
Errors related to signature generation errors.
Definition jwt.h:248
+
token_verification_error
Errors related to token verification errors.
Definition jwt.h:316
+
evp_pkey_handle 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:775
+
evp_pkey_handle 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:830
+
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:499
+
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:596
+
std::string bn2raw(const BIGNUM *bn)
Convert a OpenSSL BIGNUM to a std::string.
Definition jwt.h:874
+
std::string convert_der_to_pem(const std::string &cert_der_str, std::error_code &ec)
Convert the certificate provided as DER to PEM.
Definition jwt.h:553
+
evp_pkey_handle 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:734
+
std::unique_ptr< BIGNUM, decltype(&BN_free)> raw2bn(const std::string &raw)
Convert an std::string to a OpenSSL BIGNUM.
Definition jwt.h:886
+
evp_pkey_handle 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:680
+
type
Generic JSON types used in JWTs.
Definition jwt.h:1825
+
JSON Web Token.
Definition base.h:21
+
verifier< Clock, json_traits > verify(Clock c)
Create a verifier using the given clock.
Definition jwt.h:3577
+
builder< json_traits > create()
Return a builder instance to create a new token.
Definition jwt.h:3602
+
jwk< json_traits > parse_jwk(const typename json_traits::string_type &jwk_)
Parse a single JSON Web Key.
Definition jwt.h:3638
+
jwks< json_traits > parse_jwks(const typename json_traits::string_type &jwks_)
Parse a JSON Web Key Set.
Definition jwt.h:3648
+
verifier< default_clock, traits::boost_json > verify()
Create a verifier using the default clock.
Definition defaults.h:23
+
std::chrono::system_clock::time_point date
Default system time point in UTC.
Definition jwt.h:89
+
decoded_jwt< json_traits > decode(const typename json_traits::string_type &token, Decode decode)
Decode a token.
Definition jwt.h:3615
+
Default clock class using std::chrono::system_clock as a backend.
Definition jwt.h:3584
+
Attempt to access claim was unsuccessful.
Definition jwt.h:2237
+
+
Attempt to parse JSON was unsuccessful.
Definition jwt.h:2231
+
+
+
+
+
Checks that the current time is after the time specified in the given claim.
Definition jwt.h:2960
+
Checks that the current time is before the time specified in the given claim.
Definition jwt.h:2943
+
This is the default operation and does case sensitive matching.
Definition jwt.h:2914
+
Checks if the claim is a string and does an case insensitive comparison.
Definition jwt.h:3007
+
Checks if the given set is a subset of the set inside the token.
Definition jwt.h:2978
+
This is the base container which holds the token that need to be verified.
Definition jwt.h:2866
+