JWT-CPP v0.7.1
A header only library for creating and validating JSON Web Tokens (JWT) in C++
Loading...
Searching...
No Matches
jwt.h
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 "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/rsa.h>
22#include <openssl/ssl.h>
23
24#include <algorithm>
25#include <chrono>
26#include <climits>
27#include <cmath>
28#include <cstring>
29#include <functional>
30#include <iterator>
31#include <locale>
32#include <memory>
33#include <set>
34#include <system_error>
35#include <type_traits>
36#include <unordered_map>
37#include <utility>
38#include <vector>
39
40#if __cplusplus >= 201402L
41#ifdef __has_include
42#if __has_include(<experimental/type_traits>)
43#include <experimental/type_traits>
44#endif
45#endif
46#endif
47
48#if OPENSSL_VERSION_NUMBER >= 0x30000000L // 3.0.0
49#define JWT_OPENSSL_3_0
50#include <openssl/param_build.h>
51#elif OPENSSL_VERSION_NUMBER >= 0x10101000L // 1.1.1
52#define JWT_OPENSSL_1_1_1
53#elif OPENSSL_VERSION_NUMBER >= 0x10100000L // 1.1.0
54#define JWT_OPENSSL_1_1_0
55#elif OPENSSL_VERSION_NUMBER >= 0x10000000L // 1.0.0
56#define JWT_OPENSSL_1_0_0
57#endif
58
59#if defined(LIBRESSL_VERSION_NUMBER)
60#if LIBRESSL_VERSION_NUMBER >= 0x3050300fL
61#define JWT_OPENSSL_1_1_0
62#else
63#define JWT_OPENSSL_1_0_0
64#endif
65#endif
66
67#if defined(LIBWOLFSSL_VERSION_HEX)
68#define JWT_OPENSSL_1_1_1
69#endif
70
71#ifndef JWT_CLAIM_EXPLICIT
72#define JWT_CLAIM_EXPLICIT explicit
73#endif
74
82namespace jwt {
86 using date = std::chrono::system_clock::time_point;
87
91 namespace error {
92 struct signature_verification_exception : public std::system_error {
93 using system_error::system_error;
94 };
95 struct signature_generation_exception : public std::system_error {
96 using system_error::system_error;
97 };
98 struct rsa_exception : public std::system_error {
99 using system_error::system_error;
100 };
101 struct ecdsa_exception : public std::system_error {
102 using system_error::system_error;
103 };
104 struct token_verification_exception : public std::system_error {
105 using system_error::system_error;
106 };
110 enum class rsa_error {
111 ok = 0,
112 cert_load_failed = 10,
113 get_key_failed,
114 write_key_failed,
115 write_cert_failed,
116 convert_to_pem_failed,
117 load_key_bio_write,
118 load_key_bio_read,
119 create_mem_bio_failed,
120 no_key_provided,
121 set_rsa_failed,
122 create_context_failed
123 };
127 inline std::error_category& rsa_error_category() {
128 class rsa_error_cat : public std::error_category {
129 public:
130 const char* name() const noexcept override { return "rsa_error"; };
131 std::string message(int ev) const override {
132 switch (static_cast<rsa_error>(ev)) {
133 case rsa_error::ok: return "no error";
134 case rsa_error::cert_load_failed: return "error loading cert into memory";
135 case rsa_error::get_key_failed: return "error getting key from certificate";
136 case rsa_error::write_key_failed: return "error writing key data in PEM format";
137 case rsa_error::write_cert_failed: return "error writing cert data in PEM format";
138 case rsa_error::convert_to_pem_failed: return "failed to convert key to pem";
139 case rsa_error::load_key_bio_write: return "failed to load key: bio write failed";
140 case rsa_error::load_key_bio_read: return "failed to load key: bio read failed";
141 case rsa_error::create_mem_bio_failed: return "failed to create memory bio";
142 case rsa_error::no_key_provided: return "at least one of public or private key need to be present";
143 case rsa_error::set_rsa_failed: return "set modulus and exponent to RSA failed";
144 case rsa_error::create_context_failed: return "failed to create context";
145 default: return "unknown RSA error";
146 }
147 }
148 };
149 static rsa_error_cat cat;
150 return cat;
151 }
155 inline std::error_code make_error_code(rsa_error e) { return {static_cast<int>(e), rsa_error_category()}; }
159 enum class ecdsa_error {
160 ok = 0,
161 load_key_bio_write = 10,
162 load_key_bio_read,
163 create_mem_bio_failed,
164 no_key_provided,
165 invalid_key_size,
166 invalid_key,
167 create_context_failed,
168 cert_load_failed,
169 get_key_failed,
170 write_key_failed,
171 write_cert_failed,
172 convert_to_pem_failed,
173 unknown_curve,
174 set_ecdsa_failed
175 };
179 inline std::error_category& ecdsa_error_category() {
180 class ecdsa_error_cat : public std::error_category {
181 public:
182 const char* name() const noexcept override { return "ecdsa_error"; };
183 std::string message(int ev) const override {
184 switch (static_cast<ecdsa_error>(ev)) {
185 case ecdsa_error::ok: return "no error";
186 case ecdsa_error::load_key_bio_write: return "failed to load key: bio write failed";
187 case ecdsa_error::load_key_bio_read: return "failed to load key: bio read failed";
188 case ecdsa_error::create_mem_bio_failed: return "failed to create memory bio";
189 case ecdsa_error::no_key_provided:
190 return "at least one of public or private key need to be present";
191 case ecdsa_error::invalid_key_size: return "invalid key size";
192 case ecdsa_error::invalid_key: return "invalid key";
193 case ecdsa_error::create_context_failed: return "failed to create context";
194 case ecdsa_error::cert_load_failed: return "error loading cert into memory";
195 case ecdsa_error::get_key_failed: return "error getting key from certificate";
196 case ecdsa_error::write_key_failed: return "error writing key data in PEM format";
197 case ecdsa_error::write_cert_failed: return "error writing cert data in PEM format";
198 case ecdsa_error::convert_to_pem_failed: return "failed to convert key to pem";
199 case ecdsa_error::unknown_curve: return "unknown curve";
200 case ecdsa_error::set_ecdsa_failed: return "set parameters to ECDSA failed";
201 default: return "unknown ECDSA error";
202 }
203 }
204 };
205 static ecdsa_error_cat cat;
206 return cat;
207 }
211 inline std::error_code make_error_code(ecdsa_error e) { return {static_cast<int>(e), ecdsa_error_category()}; }
212
217 ok = 0,
218 invalid_signature = 10,
219 create_context_failed,
220 verifyinit_failed,
221 verifyupdate_failed,
222 verifyfinal_failed,
223 get_key_failed,
224 set_rsa_pss_saltlen_failed,
225 signature_encoding_failed
226 };
230 inline std::error_category& signature_verification_error_category() {
231 class verification_error_cat : public std::error_category {
232 public:
233 const char* name() const noexcept override { return "signature_verification_error"; };
234 std::string message(int ev) const override {
235 switch (static_cast<signature_verification_error>(ev)) {
236 case signature_verification_error::ok: return "no error";
237 case signature_verification_error::invalid_signature: return "invalid signature";
238 case signature_verification_error::create_context_failed:
239 return "failed to verify signature: could not create context";
240 case signature_verification_error::verifyinit_failed:
241 return "failed to verify signature: VerifyInit failed";
242 case signature_verification_error::verifyupdate_failed:
243 return "failed to verify signature: VerifyUpdate failed";
244 case signature_verification_error::verifyfinal_failed:
245 return "failed to verify signature: VerifyFinal failed";
246 case signature_verification_error::get_key_failed:
247 return "failed to verify signature: Could not get key";
248 case signature_verification_error::set_rsa_pss_saltlen_failed:
249 return "failed to verify signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
250 case signature_verification_error::signature_encoding_failed:
251 return "failed to verify signature: i2d_ECDSA_SIG failed";
252 default: return "unknown signature verification error";
253 }
254 }
255 };
256 static verification_error_cat cat;
257 return cat;
258 }
263 return {static_cast<int>(e), signature_verification_error_category()};
264 }
265
270 ok = 0,
271 hmac_failed = 10,
272 create_context_failed,
273 signinit_failed,
274 signupdate_failed,
275 signfinal_failed,
276 ecdsa_do_sign_failed,
277 digestinit_failed,
278 digestupdate_failed,
279 digestfinal_failed,
280 rsa_padding_failed,
281 rsa_private_encrypt_failed,
282 get_key_failed,
283 set_rsa_pss_saltlen_failed,
284 signature_decoding_failed
285 };
289 inline std::error_category& signature_generation_error_category() {
290 class signature_generation_error_cat : public std::error_category {
291 public:
292 const char* name() const noexcept override { return "signature_generation_error"; };
293 std::string message(int ev) const override {
294 switch (static_cast<signature_generation_error>(ev)) {
295 case signature_generation_error::ok: return "no error";
296 case signature_generation_error::hmac_failed: return "hmac failed";
297 case signature_generation_error::create_context_failed:
298 return "failed to create signature: could not create context";
299 case signature_generation_error::signinit_failed:
300 return "failed to create signature: SignInit failed";
301 case signature_generation_error::signupdate_failed:
302 return "failed to create signature: SignUpdate failed";
303 case signature_generation_error::signfinal_failed:
304 return "failed to create signature: SignFinal failed";
305 case signature_generation_error::ecdsa_do_sign_failed: return "failed to generate ecdsa signature";
306 case signature_generation_error::digestinit_failed:
307 return "failed to create signature: DigestInit failed";
308 case signature_generation_error::digestupdate_failed:
309 return "failed to create signature: DigestUpdate failed";
310 case signature_generation_error::digestfinal_failed:
311 return "failed to create signature: DigestFinal failed";
312 case signature_generation_error::rsa_padding_failed:
313 return "failed to create signature: EVP_PKEY_CTX_set_rsa_padding failed";
314 case signature_generation_error::rsa_private_encrypt_failed:
315 return "failed to create signature: RSA_private_encrypt failed";
316 case signature_generation_error::get_key_failed:
317 return "failed to generate signature: Could not get key";
318 case signature_generation_error::set_rsa_pss_saltlen_failed:
319 return "failed to create signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
320 case signature_generation_error::signature_decoding_failed:
321 return "failed to create signature: d2i_ECDSA_SIG failed";
322 default: return "unknown signature generation error";
323 }
324 }
325 };
326 static signature_generation_error_cat cat = {};
327 return cat;
328 }
332 inline std::error_code make_error_code(signature_generation_error e) {
333 return {static_cast<int>(e), signature_generation_error_category()};
334 }
335
340 ok = 0,
341 wrong_algorithm = 10,
342 missing_claim,
343 claim_type_missmatch,
344 claim_value_missmatch,
345 token_expired,
346 audience_missmatch
347 };
351 inline std::error_category& token_verification_error_category() {
352 class token_verification_error_cat : public std::error_category {
353 public:
354 const char* name() const noexcept override { return "token_verification_error"; };
355 std::string message(int ev) const override {
356 switch (static_cast<token_verification_error>(ev)) {
357 case token_verification_error::ok: return "no error";
358 case token_verification_error::wrong_algorithm: return "wrong algorithm";
359 case token_verification_error::missing_claim: return "decoded JWT is missing required claim(s)";
360 case token_verification_error::claim_type_missmatch:
361 return "claim type does not match expected type";
362 case token_verification_error::claim_value_missmatch:
363 return "claim value does not match expected value";
364 case token_verification_error::token_expired: return "token expired";
365 case token_verification_error::audience_missmatch:
366 return "token doesn't contain the required audience";
367 default: return "unknown token verification error";
368 }
369 }
370 };
371 static token_verification_error_cat cat = {};
372 return cat;
373 }
377 inline std::error_code make_error_code(token_verification_error e) {
378 return {static_cast<int>(e), token_verification_error_category()};
379 }
383 inline void throw_if_error(std::error_code ec) {
384 if (ec) {
385 if (ec.category() == rsa_error_category()) throw rsa_exception(ec);
386 if (ec.category() == ecdsa_error_category()) throw ecdsa_exception(ec);
387 if (ec.category() == signature_verification_error_category())
390 if (ec.category() == token_verification_error_category()) throw token_verification_exception(ec);
391 }
392 }
393 } // namespace error
394} // namespace jwt
395
396namespace std {
397 template<>
398 struct is_error_code_enum<jwt::error::rsa_error> : true_type {};
399 template<>
400 struct is_error_code_enum<jwt::error::ecdsa_error> : true_type {};
401 template<>
402 struct is_error_code_enum<jwt::error::signature_verification_error> : true_type {};
403 template<>
404 struct is_error_code_enum<jwt::error::signature_generation_error> : true_type {};
405 template<>
406 struct is_error_code_enum<jwt::error::token_verification_error> : true_type {};
407} // namespace std
408
409namespace jwt {
417 namespace helper {
426 public:
430 constexpr evp_pkey_handle() noexcept = default;
431#ifdef JWT_OPENSSL_1_0_0
436 explicit evp_pkey_handle(EVP_PKEY* key) { m_key = std::shared_ptr<EVP_PKEY>(key, EVP_PKEY_free); }
437
438 EVP_PKEY* get() const noexcept { return m_key.get(); }
439 bool operator!() const noexcept { return m_key == nullptr; }
440 explicit operator bool() const noexcept { return m_key != nullptr; }
441
442 private:
443 std::shared_ptr<EVP_PKEY> m_key{nullptr};
444#else
449 explicit constexpr evp_pkey_handle(EVP_PKEY* key) noexcept : m_key{key} {}
450 evp_pkey_handle(const evp_pkey_handle& other) : m_key{other.m_key} {
451 if (m_key != nullptr && EVP_PKEY_up_ref(m_key) != 1) throw std::runtime_error("EVP_PKEY_up_ref failed");
452 }
453// C++11 requires the body of a constexpr constructor to be empty
454#if __cplusplus >= 201402L
455 constexpr
456#endif
457 evp_pkey_handle(evp_pkey_handle&& other) noexcept
458 : m_key{other.m_key} {
459 other.m_key = nullptr;
460 }
461 evp_pkey_handle& operator=(const evp_pkey_handle& other) {
462 if (&other == this) return *this;
463 decrement_ref_count(m_key);
464 m_key = other.m_key;
465 increment_ref_count(m_key);
466 return *this;
467 }
468 evp_pkey_handle& operator=(evp_pkey_handle&& other) noexcept {
469 if (&other == this) return *this;
470 decrement_ref_count(m_key);
471 m_key = other.m_key;
472 other.m_key = nullptr;
473 return *this;
474 }
475 evp_pkey_handle& operator=(EVP_PKEY* key) {
476 decrement_ref_count(m_key);
477 m_key = key;
478 increment_ref_count(m_key);
479 return *this;
480 }
481 ~evp_pkey_handle() noexcept { decrement_ref_count(m_key); }
482
483 EVP_PKEY* get() const noexcept { return m_key; }
484 bool operator!() const noexcept { return m_key == nullptr; }
485 explicit operator bool() const noexcept { return m_key != nullptr; }
486
487 private:
488 EVP_PKEY* m_key{nullptr};
489
490 static void increment_ref_count(EVP_PKEY* key) {
491 if (key != nullptr && EVP_PKEY_up_ref(key) != 1) throw std::runtime_error("EVP_PKEY_up_ref failed");
492 }
493 static void decrement_ref_count(EVP_PKEY* key) noexcept {
494 if (key != nullptr) EVP_PKEY_free(key);
495 }
496#endif
497 };
498
499 inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio() {
500 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(BIO_new(BIO_s_mem()), BIO_free_all);
501 }
502
503 inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio(const std::string& data) {
504 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(
505#if OPENSSL_VERSION_NUMBER <= 0x10100003L
506 BIO_new_mem_buf(const_cast<char*>(data.data()), static_cast<int>(data.size())), BIO_free_all
507#else
508 BIO_new_mem_buf(data.data(), static_cast<int>(data.size())), BIO_free_all
509#endif
510 );
511 }
512
513 template<typename error_category = error::rsa_error>
514 std::string write_bio_to_string(std::unique_ptr<BIO, decltype(&BIO_free_all)>& bio_out, std::error_code& ec) {
515 char* ptr = nullptr;
516 auto len = BIO_get_mem_data(bio_out.get(), &ptr);
517 if (len <= 0 || ptr == nullptr) {
518 ec = error_category::convert_to_pem_failed;
519 return {};
520 }
521 return {ptr, static_cast<size_t>(len)};
522 }
523
524 inline std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> make_evp_md_ctx() {
525 return
526#ifdef JWT_OPENSSL_1_0_0
527 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), &EVP_MD_CTX_destroy);
528#else
529 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), &EVP_MD_CTX_free);
530#endif
531 }
532
541 template<typename error_category = error::rsa_error>
542 std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw, std::error_code& ec) {
543 ec.clear();
544 auto certbio = make_mem_buf_bio(certstr);
545 auto keybio = make_mem_buf_bio();
546 if (!certbio || !keybio) {
547 ec = error_category::create_mem_bio_failed;
548 return {};
549 }
550
551 std::unique_ptr<X509, decltype(&X509_free)> cert(
552 PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())), X509_free);
553 if (!cert) {
554 ec = error_category::cert_load_failed;
555 return {};
556 }
557 std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()), EVP_PKEY_free);
558 if (!key) {
559 ec = error_category::get_key_failed;
560 return {};
561 }
562 if (PEM_write_bio_PUBKEY(keybio.get(), key.get()) == 0) {
563 ec = error_category::write_key_failed;
564 return {};
565 }
566
567 return write_bio_to_string<error_category>(keybio, ec);
568 }
569
578 template<typename error_category = error::rsa_error>
579 std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw = "") {
580 std::error_code ec;
581 auto res = extract_pubkey_from_cert<error_category>(certstr, pw, ec);
583 return res;
584 }
585
592 inline std::string convert_der_to_pem(const std::string& cert_der_str, std::error_code& ec) {
593 ec.clear();
594
595 auto c_str = reinterpret_cast<const unsigned char*>(cert_der_str.c_str());
596
597 std::unique_ptr<X509, decltype(&X509_free)> cert(
598 d2i_X509(NULL, &c_str, static_cast<int>(cert_der_str.size())), X509_free);
599 auto certbio = make_mem_buf_bio();
600 if (!cert || !certbio) {
601 ec = error::rsa_error::create_mem_bio_failed;
602 return {};
603 }
604
605 if (!PEM_write_bio_X509(certbio.get(), cert.get())) {
606 ec = error::rsa_error::write_cert_failed;
607 return {};
608 }
609
610 return write_bio_to_string(certbio, ec);
611 }
612
627 template<typename Decode>
628 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode,
629 std::error_code& ec) {
630 ec.clear();
631 const auto decoded_str = decode(cert_base64_der_str);
632 return convert_der_to_pem(decoded_str, ec);
633 }
634
649 template<typename Decode>
650 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode) {
651 std::error_code ec;
652 auto res = convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
654 return res;
655 }
656
663 inline std::string convert_der_to_pem(const std::string& cert_der_str) {
664 std::error_code ec;
665 auto res = convert_der_to_pem(cert_der_str, ec);
667 return res;
668 }
669
670#ifndef JWT_DISABLE_BASE64
680 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, std::error_code& ec) {
681 auto decode = [](const std::string& token) {
682 return base::decode<alphabet::base64>(base::pad<alphabet::base64>(token));
683 };
684 return convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
685 }
686
696 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str) {
697 std::error_code ec;
698 auto res = convert_base64_der_to_pem(cert_base64_der_str, ec);
700 return res;
701 }
702#endif
713 template<typename error_category = error::rsa_error>
714 evp_pkey_handle load_public_key_from_string(const std::string& key, const std::string& password,
715 std::error_code& ec) {
716 ec.clear();
717 auto pubkey_bio = make_mem_buf_bio();
718 if (!pubkey_bio) {
719 ec = error_category::create_mem_bio_failed;
720 return {};
721 }
722 if (key.substr(0, 27) == "-----BEGIN CERTIFICATE-----") {
723 auto epkey = helper::extract_pubkey_from_cert<error_category>(key, password, ec);
724 if (ec) return {};
725 // Ensure the size fits into an int before casting
726 if (epkey.size() > static_cast<std::size_t>((std::numeric_limits<int>::max)())) {
727 ec = error_category::load_key_bio_write; // Add an appropriate error here
728 return {};
729 }
730 int len = static_cast<int>(epkey.size());
731 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len) {
732 ec = error_category::load_key_bio_write;
733 return {};
734 }
735 } else {
736 // Ensure the size fits into an int before casting
737 if (key.size() > static_cast<std::size_t>((std::numeric_limits<int>::max)())) {
738 ec = error_category::load_key_bio_write; // Add an appropriate error here
739 return {};
740 }
741 int len = static_cast<int>(key.size());
742 if (BIO_write(pubkey_bio.get(), key.data(), len) != len) {
743 ec = error_category::load_key_bio_write;
744 return {};
745 }
746 }
747
748 evp_pkey_handle pkey(PEM_read_bio_PUBKEY(
749 pubkey_bio.get(), nullptr, nullptr,
750 (void*)password.data())); // NOLINT(google-readability-casting) requires `const_cast`
751 if (!pkey) ec = error_category::load_key_bio_read;
752 return pkey;
753 }
754
765 template<typename error_category = error::rsa_error>
766 inline evp_pkey_handle load_public_key_from_string(const std::string& key, const std::string& password = "") {
767 std::error_code ec;
768 auto res = load_public_key_from_string<error_category>(key, password, ec);
770 return res;
771 }
772
781 template<typename error_category = error::rsa_error>
782 inline evp_pkey_handle load_private_key_from_string(const std::string& key, const std::string& password,
783 std::error_code& ec) {
784 ec.clear();
785 auto private_key_bio = make_mem_buf_bio();
786 if (!private_key_bio) {
787 ec = error_category::create_mem_bio_failed;
788 return {};
789 }
790 const int len = static_cast<int>(key.size());
791 if (BIO_write(private_key_bio.get(), key.data(), len) != len) {
792 ec = error_category::load_key_bio_write;
793 return {};
794 }
795 evp_pkey_handle pkey(
796 PEM_read_bio_PrivateKey(private_key_bio.get(), nullptr, nullptr, const_cast<char*>(password.c_str())));
797 if (!pkey) ec = error_category::load_key_bio_read;
798 return pkey;
799 }
800
809 template<typename error_category = error::rsa_error>
810 inline evp_pkey_handle load_private_key_from_string(const std::string& key, const std::string& password = "") {
811 std::error_code ec;
812 auto res = load_private_key_from_string<error_category>(key, password, ec);
814 return res;
815 }
816
828 inline evp_pkey_handle load_public_ec_key_from_string(const std::string& key, const std::string& password,
829 std::error_code& ec) {
830 return load_public_key_from_string<error::ecdsa_error>(key, password, ec);
831 }
832
838 inline
839#ifdef JWT_OPENSSL_1_0_0
840 std::string
841 bn2raw(BIGNUM* bn)
842#else
843 std::string
844 bn2raw(const BIGNUM* bn)
845#endif
846 {
847 std::string res(BN_num_bytes(bn), '\0');
848 BN_bn2bin(bn, (unsigned char*)res.data()); // NOLINT(google-readability-casting) requires `const_cast`
849 return res;
850 }
857 inline std::unique_ptr<BIGNUM, decltype(&BN_free)> raw2bn(const std::string& raw, std::error_code& ec) {
858 auto bn =
859 BN_bin2bn(reinterpret_cast<const unsigned char*>(raw.data()), static_cast<int>(raw.size()), nullptr);
860 // https://www.openssl.org/docs/man1.1.1/man3/BN_bin2bn.html#RETURN-VALUES
861 if (!bn) {
862 ec = error::rsa_error::set_rsa_failed;
863 return {nullptr, BN_free};
864 }
865 return {bn, BN_free};
866 }
872 inline std::unique_ptr<BIGNUM, decltype(&BN_free)> raw2bn(const std::string& raw) {
873 std::error_code ec;
874 auto res = raw2bn(raw, ec);
876 return res;
877 }
878
890 inline evp_pkey_handle load_public_ec_key_from_string(const std::string& key,
891 const std::string& password = "") {
892 std::error_code ec;
893 auto res = load_public_key_from_string<error::ecdsa_error>(key, password, ec);
895 return res;
896 }
897
907 inline evp_pkey_handle load_private_ec_key_from_string(const std::string& key, const std::string& password,
908 std::error_code& ec) {
909 return load_private_key_from_string<error::ecdsa_error>(key, password, ec);
910 }
911
926 template<typename Decode>
927 std::string create_public_key_from_rsa_components(const std::string& modulus, const std::string& exponent,
928 Decode decode, std::error_code& ec) {
929 ec.clear();
930 auto decoded_modulus = decode(modulus);
931 auto decoded_exponent = decode(exponent);
932
933 auto n = helper::raw2bn(decoded_modulus, ec);
934 if (ec) return {};
935 auto e = helper::raw2bn(decoded_exponent, ec);
936 if (ec) return {};
937
938#if defined(JWT_OPENSSL_3_0)
939 // OpenSSL deprecated mutable keys and there is a new way for making them
940 // https://mta.openssl.org/pipermail/openssl-users/2021-July/013994.html
941 // https://www.openssl.org/docs/man3.1/man3/OSSL_PARAM_BLD_new.html#Example-2
942 std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)> param_bld(OSSL_PARAM_BLD_new(),
943 OSSL_PARAM_BLD_free);
944 if (!param_bld) {
945 ec = error::rsa_error::create_context_failed;
946 return {};
947 }
948
949 if (OSSL_PARAM_BLD_push_BN(param_bld.get(), "n", n.get()) != 1 ||
950 OSSL_PARAM_BLD_push_BN(param_bld.get(), "e", e.get()) != 1) {
951 ec = error::rsa_error::set_rsa_failed;
952 return {};
953 }
954
955 std::unique_ptr<OSSL_PARAM, decltype(&OSSL_PARAM_free)> params(OSSL_PARAM_BLD_to_param(param_bld.get()),
956 OSSL_PARAM_free);
957 if (!params) {
958 ec = error::rsa_error::set_rsa_failed;
959 return {};
960 }
961
962 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
963 EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr), EVP_PKEY_CTX_free);
964 if (!ctx) {
965 ec = error::rsa_error::create_context_failed;
966 return {};
967 }
968
969 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html#EXAMPLES
970 // Error codes based on https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_fromdata_init.html#RETURN-VALUES
971 EVP_PKEY* pkey = NULL;
972 if (EVP_PKEY_fromdata_init(ctx.get()) <= 0 ||
973 EVP_PKEY_fromdata(ctx.get(), &pkey, EVP_PKEY_KEYPAIR, params.get()) <= 0) {
974 // It's unclear if this can fail after allocating but free it anyways
975 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html
976 EVP_PKEY_free(pkey);
977
978 ec = error::rsa_error::cert_load_failed;
979 return {};
980 }
981
982 // Transfer ownership so we get ref counter and cleanup
983 evp_pkey_handle rsa(pkey);
984
985#else
986 std::unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
987
988#if defined(JWT_OPENSSL_1_1_1) || defined(JWT_OPENSSL_1_1_0)
989 // After this RSA_free will also free the n and e big numbers
990 // See https://github.com/Thalhammer/jwt-cpp/pull/298#discussion_r1282619186
991 if (RSA_set0_key(rsa.get(), n.get(), e.get(), nullptr) == 1) {
992 // This can only fail we passed in NULL for `n` or `e`
993 // https://github.com/openssl/openssl/blob/d6e4056805f54bb1a0ef41fa3a6a35b70c94edba/crypto/rsa/rsa_lib.c#L396
994 // So to make sure there is no memory leak, we hold the references
995 n.release();
996 e.release();
997 } else {
998 ec = error::rsa_error::set_rsa_failed;
999 return {};
1000 }
1001#elif defined(JWT_OPENSSL_1_0_0)
1002 rsa->e = e.release();
1003 rsa->n = n.release();
1004 rsa->d = nullptr;
1005#endif
1006#endif
1007
1008 auto pub_key_bio = make_mem_buf_bio();
1009 if (!pub_key_bio) {
1010 ec = error::rsa_error::create_mem_bio_failed;
1011 return {};
1012 }
1013
1014 auto write_pem_to_bio =
1015#if defined(JWT_OPENSSL_3_0)
1016 // https://www.openssl.org/docs/man3.1/man3/PEM_write_bio_RSA_PUBKEY.html
1017 &PEM_write_bio_PUBKEY;
1018#else
1019 &PEM_write_bio_RSA_PUBKEY;
1020#endif
1021 if (write_pem_to_bio(pub_key_bio.get(), rsa.get()) != 1) {
1022 ec = error::rsa_error::load_key_bio_write;
1023 return {};
1024 }
1025
1026 return write_bio_to_string<error::rsa_error>(pub_key_bio, ec);
1027 }
1028
1042 template<typename Decode>
1043 std::string create_public_key_from_rsa_components(const std::string& modulus, const std::string& exponent,
1044 Decode decode) {
1045 std::error_code ec;
1046 auto res = create_public_key_from_rsa_components(modulus, exponent, decode, ec);
1048 return res;
1049 }
1050
1051#ifndef JWT_DISABLE_BASE64
1062 inline std::string create_public_key_from_rsa_components(const std::string& modulus,
1063 const std::string& exponent, std::error_code& ec) {
1064 auto decode = [](const std::string& token) {
1065 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(token));
1066 };
1067 return create_public_key_from_rsa_components(modulus, exponent, std::move(decode), ec);
1068 }
1078 inline std::string create_public_key_from_rsa_components(const std::string& modulus,
1079 const std::string& exponent) {
1080 std::error_code ec;
1081 auto res = create_public_key_from_rsa_components(modulus, exponent, ec);
1083 return res;
1084 }
1085#endif
1096 const std::string& password = "") {
1097 std::error_code ec;
1098 auto res = load_private_key_from_string<error::ecdsa_error>(key, password, ec);
1100 return res;
1101 }
1102
1103#if defined(JWT_OPENSSL_3_0)
1104
1112 inline std::string curve2group(const std::string curve, std::error_code& ec) {
1113 if (curve == "P-256") {
1114 return "prime256v1";
1115 } else if (curve == "P-384") {
1116 return "secp384r1";
1117 } else if (curve == "P-521") {
1118 return "secp521r1";
1119 } else {
1120 ec = jwt::error::ecdsa_error::unknown_curve;
1121 return {};
1122 }
1123 }
1124
1125#else
1126
1134 inline int curve2nid(const std::string curve, std::error_code& ec) {
1135 if (curve == "P-256") {
1136 return NID_X9_62_prime256v1;
1137 } else if (curve == "P-384") {
1138 return NID_secp384r1;
1139 } else if (curve == "P-521") {
1140 return NID_secp521r1;
1141 } else {
1142 ec = jwt::error::ecdsa_error::unknown_curve;
1143 return {};
1144 }
1145 }
1146
1147#endif
1148
1164 template<typename Decode>
1165 std::string create_public_key_from_ec_components(const std::string& curve, const std::string& x,
1166 const std::string& y, Decode decode, std::error_code& ec) {
1167 ec.clear();
1168 auto decoded_x = decode(x);
1169 auto decoded_y = decode(y);
1170
1171#if defined(JWT_OPENSSL_3_0)
1172 // OpenSSL deprecated mutable keys and there is a new way for making them
1173 // https://mta.openssl.org/pipermail/openssl-users/2021-July/013994.html
1174 // https://www.openssl.org/docs/man3.1/man3/OSSL_PARAM_BLD_new.html#Example-2
1175 std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)> param_bld(OSSL_PARAM_BLD_new(),
1176 OSSL_PARAM_BLD_free);
1177 if (!param_bld) {
1178 ec = error::ecdsa_error::create_context_failed;
1179 return {};
1180 }
1181
1182 std::string group = helper::curve2group(curve, ec);
1183 if (ec) return {};
1184
1185 // https://github.com/openssl/openssl/issues/16270#issuecomment-895734092
1186 std::string pub = std::string("\x04").append(decoded_x).append(decoded_y);
1187
1188 if (OSSL_PARAM_BLD_push_utf8_string(param_bld.get(), "group", group.data(), group.size()) != 1 ||
1189 OSSL_PARAM_BLD_push_octet_string(param_bld.get(), "pub", pub.data(), pub.size()) != 1) {
1190 ec = error::ecdsa_error::set_ecdsa_failed;
1191 return {};
1192 }
1193
1194 std::unique_ptr<OSSL_PARAM, decltype(&OSSL_PARAM_free)> params(OSSL_PARAM_BLD_to_param(param_bld.get()),
1195 OSSL_PARAM_free);
1196 if (!params) {
1197 ec = error::ecdsa_error::set_ecdsa_failed;
1198 return {};
1199 }
1200
1201 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
1202 EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr), EVP_PKEY_CTX_free);
1203 if (!ctx) {
1204 ec = error::ecdsa_error::create_context_failed;
1205 return {};
1206 }
1207
1208 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html#EXAMPLES
1209 // Error codes based on https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_fromdata_init.html#RETURN-VALUES
1210 EVP_PKEY* pkey = NULL;
1211 if (EVP_PKEY_fromdata_init(ctx.get()) <= 0 ||
1212 EVP_PKEY_fromdata(ctx.get(), &pkey, EVP_PKEY_KEYPAIR, params.get()) <= 0) {
1213 // It's unclear if this can fail after allocating but free it anyways
1214 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html
1215 EVP_PKEY_free(pkey);
1216
1217 ec = error::ecdsa_error::cert_load_failed;
1218 return {};
1219 }
1220
1221 // Transfer ownership so we get ref counter and cleanup
1222 evp_pkey_handle ecdsa(pkey);
1223
1224#else
1225 int nid = helper::curve2nid(curve, ec);
1226 if (ec) return {};
1227
1228 auto qx = helper::raw2bn(decoded_x, ec);
1229 if (ec) return {};
1230 auto qy = helper::raw2bn(decoded_y, ec);
1231 if (ec) return {};
1232
1233 std::unique_ptr<EC_GROUP, decltype(&EC_GROUP_free)> ecgroup(EC_GROUP_new_by_curve_name(nid), EC_GROUP_free);
1234 if (!ecgroup) {
1235 ec = error::ecdsa_error::set_ecdsa_failed;
1236 return {};
1237 }
1238
1239 EC_GROUP_set_asn1_flag(ecgroup.get(), OPENSSL_EC_NAMED_CURVE);
1240
1241 std::unique_ptr<EC_POINT, decltype(&EC_POINT_free)> ecpoint(EC_POINT_new(ecgroup.get()), EC_POINT_free);
1242 if (!ecpoint ||
1243 EC_POINT_set_affine_coordinates_GFp(ecgroup.get(), ecpoint.get(), qx.get(), qy.get(), nullptr) != 1) {
1244 ec = error::ecdsa_error::set_ecdsa_failed;
1245 return {};
1246 }
1247
1248 std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ecdsa(EC_KEY_new(), EC_KEY_free);
1249 if (!ecdsa || EC_KEY_set_group(ecdsa.get(), ecgroup.get()) != 1 ||
1250 EC_KEY_set_public_key(ecdsa.get(), ecpoint.get()) != 1) {
1251 ec = error::ecdsa_error::set_ecdsa_failed;
1252 return {};
1253 }
1254
1255#endif
1256
1257 auto pub_key_bio = make_mem_buf_bio();
1258 if (!pub_key_bio) {
1259 ec = error::ecdsa_error::create_mem_bio_failed;
1260 return {};
1261 }
1262
1263 auto write_pem_to_bio =
1264#if defined(JWT_OPENSSL_3_0)
1265 // https://www.openssl.org/docs/man3.1/man3/PEM_write_bio_EC_PUBKEY.html
1266 &PEM_write_bio_PUBKEY;
1267#else
1268 &PEM_write_bio_EC_PUBKEY;
1269#endif
1270 if (write_pem_to_bio(pub_key_bio.get(), ecdsa.get()) != 1) {
1271 ec = error::ecdsa_error::load_key_bio_write;
1272 return {};
1273 }
1274
1275 return write_bio_to_string<error::ecdsa_error>(pub_key_bio, ec);
1276 }
1277
1292 template<typename Decode>
1293 std::string create_public_key_from_ec_components(const std::string& curve, const std::string& x,
1294 const std::string& y, Decode decode) {
1295 std::error_code ec;
1296 auto res = create_public_key_from_ec_components(curve, x, y, decode, ec);
1298 return res;
1299 }
1300
1301#ifndef JWT_DISABLE_BASE64
1313 inline std::string create_public_key_from_ec_components(const std::string& curve, const std::string& x,
1314 const std::string& y, std::error_code& ec) {
1315 auto decode = [](const std::string& token) {
1316 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(token));
1317 };
1318 return create_public_key_from_ec_components(curve, x, y, std::move(decode), ec);
1319 }
1330 inline std::string create_public_key_from_ec_components(const std::string& curve, const std::string& x,
1331 const std::string& y) {
1332 std::error_code ec;
1333 auto res = create_public_key_from_ec_components(curve, x, y, ec);
1335 return res;
1336 }
1337#endif
1338 } // namespace helper
1339
1349 namespace algorithm {
1357 struct none {
1361 std::string sign(const std::string& /*unused*/, std::error_code& ec) const {
1362 ec.clear();
1363 return {};
1364 }
1372 void verify(const std::string& /*unused*/, const std::string& signature, std::error_code& ec) const {
1373 ec.clear();
1374 if (!signature.empty()) { ec = error::signature_verification_error::invalid_signature; }
1375 }
1377 std::string name() const { return "none"; }
1378 };
1382 struct hmacsha {
1390 hmacsha(std::string key, const EVP_MD* (*md)(), std::string name)
1391 : secret(std::move(key)), md(md), alg_name(std::move(name)) {}
1399 std::string sign(const std::string& data, std::error_code& ec) const {
1400 ec.clear();
1401 std::string res(static_cast<size_t>(EVP_MAX_MD_SIZE), '\0');
1402 auto len = static_cast<unsigned int>(res.size());
1403 if (HMAC(md(), secret.data(), static_cast<int>(secret.size()),
1404 reinterpret_cast<const unsigned char*>(data.data()), static_cast<int>(data.size()),
1405 (unsigned char*)res.data(), // NOLINT(google-readability-casting) requires `const_cast`
1406 &len) == nullptr) {
1407 ec = error::signature_generation_error::hmac_failed;
1408 return {};
1409 }
1410 res.resize(len);
1411 return res;
1412 }
1420 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1421 ec.clear();
1422 auto res = sign(data, ec);
1423 if (ec) return;
1424
1425 bool matched = true;
1426 for (size_t i = 0; i < std::min<size_t>(res.size(), signature.size()); i++)
1427 if (res[i] != signature[i]) matched = false;
1428 if (res.size() != signature.size()) matched = false;
1429 if (!matched) {
1430 ec = error::signature_verification_error::invalid_signature;
1431 return;
1432 }
1433 }
1439 std::string name() const { return alg_name; }
1440
1441 private:
1443 const std::string secret;
1445 const EVP_MD* (*md)();
1447 const std::string alg_name;
1448 };
1452 struct rsa {
1463 rsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1464 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name)
1465 : md(md), alg_name(std::move(name)) {
1466 if (!private_key.empty()) {
1467 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1468 } else if (!public_key.empty()) {
1469 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1470 } else
1471 throw error::rsa_exception(error::rsa_error::no_key_provided);
1472 }
1480 rsa(helper::evp_pkey_handle key_pair, const EVP_MD* (*md)(), std::string name)
1481 : pkey(std::move(key_pair)), md(md), alg_name(std::move(name)) {
1482 if (!pkey) { throw error::rsa_exception(error::rsa_error::no_key_provided); }
1483 }
1490 std::string sign(const std::string& data, std::error_code& ec) const {
1491 ec.clear();
1492 auto ctx = helper::make_evp_md_ctx();
1493 if (!ctx) {
1494 ec = error::signature_generation_error::create_context_failed;
1495 return {};
1496 }
1497 if (!EVP_SignInit(ctx.get(), md())) {
1498 ec = error::signature_generation_error::signinit_failed;
1499 return {};
1500 }
1501
1502 std::string res(EVP_PKEY_size(pkey.get()), '\0');
1503 unsigned int len = 0;
1504
1505 if (!EVP_SignUpdate(ctx.get(), data.data(), data.size())) {
1506 ec = error::signature_generation_error::signupdate_failed;
1507 return {};
1508 }
1509 if (EVP_SignFinal(ctx.get(), (unsigned char*)res.data(), &len, pkey.get()) == 0) {
1510 ec = error::signature_generation_error::signfinal_failed;
1511 return {};
1512 }
1513
1514 res.resize(len);
1515 return res;
1516 }
1524 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1525 ec.clear();
1526 auto ctx = helper::make_evp_md_ctx();
1527 if (!ctx) {
1528 ec = error::signature_verification_error::create_context_failed;
1529 return;
1530 }
1531 if (!EVP_VerifyInit(ctx.get(), md())) {
1532 ec = error::signature_verification_error::verifyinit_failed;
1533 return;
1534 }
1535 if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size())) {
1536 ec = error::signature_verification_error::verifyupdate_failed;
1537 return;
1538 }
1539 auto res = EVP_VerifyFinal(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1540 static_cast<unsigned int>(signature.size()), pkey.get());
1541 if (res != 1) {
1542 ec = error::signature_verification_error::verifyfinal_failed;
1543 return;
1544 }
1545 }
1550 std::string name() const { return alg_name; }
1551
1552 private:
1556 const EVP_MD* (*md)();
1558 const std::string alg_name;
1559 };
1563 struct ecdsa {
1575 ecdsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1576 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name, size_t siglen)
1577 : md(md), alg_name(std::move(name)), signature_length(siglen) {
1578 if (!private_key.empty()) {
1579 pkey = helper::load_private_ec_key_from_string(private_key, private_key_password);
1580 check_private_key(pkey.get());
1581 } else if (!public_key.empty()) {
1582 pkey = helper::load_public_ec_key_from_string(public_key, public_key_password);
1583 check_public_key(pkey.get());
1584 } else {
1585 throw error::ecdsa_exception(error::ecdsa_error::no_key_provided);
1586 }
1587 if (!pkey) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1588
1589 size_t keysize = EVP_PKEY_bits(pkey.get());
1590 if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
1591 throw error::ecdsa_exception(error::ecdsa_error::invalid_key_size);
1592 }
1593
1602 ecdsa(helper::evp_pkey_handle key_pair, const EVP_MD* (*md)(), std::string name, size_t siglen)
1603 : pkey(std::move(key_pair)), md(md), alg_name(std::move(name)), signature_length(siglen) {
1604 if (!pkey) { throw error::ecdsa_exception(error::ecdsa_error::no_key_provided); }
1605 size_t keysize = EVP_PKEY_bits(pkey.get());
1606 if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
1607 throw error::ecdsa_exception(error::ecdsa_error::invalid_key_size);
1608 }
1609
1616 std::string sign(const std::string& data, std::error_code& ec) const {
1617 ec.clear();
1618 auto ctx = helper::make_evp_md_ctx();
1619 if (!ctx) {
1620 ec = error::signature_generation_error::create_context_failed;
1621 return {};
1622 }
1623 if (!EVP_DigestSignInit(ctx.get(), nullptr, md(), nullptr, pkey.get())) {
1624 ec = error::signature_generation_error::signinit_failed;
1625 return {};
1626 }
1627 if (!EVP_DigestUpdate(ctx.get(), data.data(), static_cast<unsigned int>(data.size()))) {
1628 ec = error::signature_generation_error::digestupdate_failed;
1629 return {};
1630 }
1631
1632 size_t len = 0;
1633 if (!EVP_DigestSignFinal(ctx.get(), nullptr, &len)) {
1634 ec = error::signature_generation_error::signfinal_failed;
1635 return {};
1636 }
1637 std::string res(len, '\0');
1638 if (!EVP_DigestSignFinal(ctx.get(), (unsigned char*)res.data(), &len)) {
1639 ec = error::signature_generation_error::signfinal_failed;
1640 return {};
1641 }
1642
1643 res.resize(len);
1644 return der_to_p1363_signature(res, ec);
1645 }
1646
1653 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1654 ec.clear();
1655 std::string der_signature = p1363_to_der_signature(signature, ec);
1656 if (ec) { return; }
1657
1658 auto ctx = helper::make_evp_md_ctx();
1659 if (!ctx) {
1660 ec = error::signature_verification_error::create_context_failed;
1661 return;
1662 }
1663 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, md(), nullptr, pkey.get())) {
1664 ec = error::signature_verification_error::verifyinit_failed;
1665 return;
1666 }
1667 if (!EVP_DigestUpdate(ctx.get(), data.data(), static_cast<unsigned int>(data.size()))) {
1668 ec = error::signature_verification_error::verifyupdate_failed;
1669 return;
1670 }
1671
1672#if OPENSSL_VERSION_NUMBER < 0x10002000L
1673 unsigned char* der_sig_data = reinterpret_cast<unsigned char*>(const_cast<char*>(der_signature.data()));
1674#else
1675 const unsigned char* der_sig_data = reinterpret_cast<const unsigned char*>(der_signature.data());
1676#endif
1677 auto res =
1678 EVP_DigestVerifyFinal(ctx.get(), der_sig_data, static_cast<unsigned int>(der_signature.length()));
1679 if (res == 0) {
1680 ec = error::signature_verification_error::invalid_signature;
1681 return;
1682 }
1683 if (res == -1) {
1684 ec = error::signature_verification_error::verifyfinal_failed;
1685 return;
1686 }
1687 }
1692 std::string name() const { return alg_name; }
1693
1694 private:
1695 static void check_public_key(EVP_PKEY* pkey) {
1696#ifdef JWT_OPENSSL_3_0
1697 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
1698 EVP_PKEY_CTX_new_from_pkey(nullptr, pkey, nullptr), EVP_PKEY_CTX_free);
1699 if (!ctx) { throw error::ecdsa_exception(error::ecdsa_error::create_context_failed); }
1700 if (EVP_PKEY_public_check(ctx.get()) != 1) {
1701 throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1702 }
1703#else
1704 std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
1705 if (!eckey) { throw error::ecdsa_exception(error::ecdsa_error::invalid_key); }
1706 if (EC_KEY_check_key(eckey.get()) == 0) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1707#endif
1708 }
1709
1710 static void check_private_key(EVP_PKEY* pkey) {
1711#ifdef JWT_OPENSSL_3_0
1712 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
1713 EVP_PKEY_CTX_new_from_pkey(nullptr, pkey, nullptr), EVP_PKEY_CTX_free);
1714 if (!ctx) { throw error::ecdsa_exception(error::ecdsa_error::create_context_failed); }
1715 if (EVP_PKEY_private_check(ctx.get()) != 1) {
1716 throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1717 }
1718#else
1719 std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
1720 if (!eckey) { throw error::ecdsa_exception(error::ecdsa_error::invalid_key); }
1721 if (EC_KEY_check_key(eckey.get()) == 0) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1722#endif
1723 }
1724
1725 std::string der_to_p1363_signature(const std::string& der_signature, std::error_code& ec) const {
1726 const unsigned char* possl_signature = reinterpret_cast<const unsigned char*>(der_signature.data());
1727 std::unique_ptr<ECDSA_SIG, decltype(&ECDSA_SIG_free)> sig(
1728 d2i_ECDSA_SIG(nullptr, &possl_signature, static_cast<long>(der_signature.length())),
1729 ECDSA_SIG_free);
1730 if (!sig) {
1731 ec = error::signature_generation_error::signature_decoding_failed;
1732 return {};
1733 }
1734
1735#ifdef JWT_OPENSSL_1_0_0
1736 auto rr = helper::bn2raw(sig->r);
1737 auto rs = helper::bn2raw(sig->s);
1738#else
1739 const BIGNUM* r;
1740 const BIGNUM* s;
1741 ECDSA_SIG_get0(sig.get(), &r, &s);
1742 auto rr = helper::bn2raw(r);
1743 auto rs = helper::bn2raw(s);
1744#endif
1745 if (rr.size() > signature_length / 2 || rs.size() > signature_length / 2)
1746 throw std::logic_error("bignum size exceeded expected length");
1747 rr.insert(0, signature_length / 2 - rr.size(), '\0');
1748 rs.insert(0, signature_length / 2 - rs.size(), '\0');
1749 return rr + rs;
1750 }
1751
1752 std::string p1363_to_der_signature(const std::string& signature, std::error_code& ec) const {
1753 ec.clear();
1754 auto r = helper::raw2bn(signature.substr(0, signature.size() / 2), ec);
1755 if (ec) return {};
1756 auto s = helper::raw2bn(signature.substr(signature.size() / 2), ec);
1757 if (ec) return {};
1758
1759 ECDSA_SIG* psig;
1760#ifdef JWT_OPENSSL_1_0_0
1761 ECDSA_SIG sig;
1762 sig.r = r.get();
1763 sig.s = s.get();
1764 psig = &sig;
1765#else
1766 std::unique_ptr<ECDSA_SIG, decltype(&ECDSA_SIG_free)> sig(ECDSA_SIG_new(), ECDSA_SIG_free);
1767 if (!sig) {
1768 ec = error::signature_verification_error::create_context_failed;
1769 return {};
1770 }
1771 ECDSA_SIG_set0(sig.get(), r.release(), s.release());
1772 psig = sig.get();
1773#endif
1774
1775 int length = i2d_ECDSA_SIG(psig, nullptr);
1776 if (length < 0) {
1777 ec = error::signature_verification_error::signature_encoding_failed;
1778 return {};
1779 }
1780 std::string der_signature(length, '\0');
1781 unsigned char* psbuffer = (unsigned char*)der_signature.data();
1782 length = i2d_ECDSA_SIG(psig, &psbuffer);
1783 if (length < 0) {
1784 ec = error::signature_verification_error::signature_encoding_failed;
1785 return {};
1786 }
1787 der_signature.resize(length);
1788 return der_signature;
1789 }
1790
1792 helper::evp_pkey_handle pkey;
1794 const EVP_MD* (*md)();
1796 const std::string alg_name;
1798 const size_t signature_length;
1799 };
1800
1801#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1810 struct eddsa {
1821 eddsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1822 const std::string& private_key_password, std::string name)
1823 : alg_name(std::move(name)) {
1824 if (!private_key.empty()) {
1825 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1826 } else if (!public_key.empty()) {
1827 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1828 } else
1829 throw error::ecdsa_exception(error::ecdsa_error::load_key_bio_read);
1830 }
1837 std::string sign(const std::string& data, std::error_code& ec) const {
1838 ec.clear();
1839 auto ctx = helper::make_evp_md_ctx();
1840 if (!ctx) {
1841 ec = error::signature_generation_error::create_context_failed;
1842 return {};
1843 }
1844 if (!EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())) {
1845 ec = error::signature_generation_error::signinit_failed;
1846 return {};
1847 }
1848
1849 size_t len = EVP_PKEY_size(pkey.get());
1850 std::string res(len, '\0');
1851
1852// LibreSSL is the special kid in the block, as it does not support EVP_DigestSign.
1853// OpenSSL on the otherhand does not support using EVP_DigestSignUpdate for eddsa, which is why we end up with this
1854// mess.
1855#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1856 ERR_clear_error();
1857 if (EVP_DigestSignUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()), data.size()) !=
1858 1) {
1859 std::cout << ERR_error_string(ERR_get_error(), NULL) << '\n';
1860 ec = error::signature_generation_error::signupdate_failed;
1861 return {};
1862 }
1863 if (EVP_DigestSignFinal(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len) != 1) {
1864 ec = error::signature_generation_error::signfinal_failed;
1865 return {};
1866 }
1867#else
1868 if (EVP_DigestSign(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len,
1869 reinterpret_cast<const unsigned char*>(data.data()), data.size()) != 1) {
1870 ec = error::signature_generation_error::signfinal_failed;
1871 return {};
1872 }
1873#endif
1874
1875 res.resize(len);
1876 return res;
1877 }
1878
1885 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1886 ec.clear();
1887 auto ctx = helper::make_evp_md_ctx();
1888 if (!ctx) {
1889 ec = error::signature_verification_error::create_context_failed;
1890 return;
1891 }
1892 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())) {
1893 ec = error::signature_verification_error::verifyinit_failed;
1894 return;
1895 }
1896// LibreSSL is the special kid in the block, as it does not support EVP_DigestVerify.
1897// OpenSSL on the otherhand does not support using EVP_DigestVerifyUpdate for eddsa, which is why we end up with this
1898// mess.
1899#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1900 if (EVP_DigestVerifyUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()),
1901 data.size()) != 1) {
1902 ec = error::signature_verification_error::verifyupdate_failed;
1903 return;
1904 }
1905 if (EVP_DigestVerifyFinal(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1906 signature.size()) != 1) {
1907 ec = error::signature_verification_error::verifyfinal_failed;
1908 return;
1909 }
1910#else
1911 auto res = EVP_DigestVerify(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1912 signature.size(), reinterpret_cast<const unsigned char*>(data.data()),
1913 data.size());
1914 if (res != 1) {
1915 ec = error::signature_verification_error::verifyfinal_failed;
1916 return;
1917 }
1918#endif
1919 }
1924 std::string name() const { return alg_name; }
1925
1926 private:
1930 const std::string alg_name;
1931 };
1932#endif
1936 struct pss {
1946 pss(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1947 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name)
1948 : md(md), alg_name(std::move(name)) {
1949 if (!private_key.empty()) {
1950 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1951 } else if (!public_key.empty()) {
1952 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1953 } else
1954 throw error::rsa_exception(error::rsa_error::no_key_provided);
1955 }
1956
1963 std::string sign(const std::string& data, std::error_code& ec) const {
1964 ec.clear();
1965 auto md_ctx = helper::make_evp_md_ctx();
1966 if (!md_ctx) {
1967 ec = error::signature_generation_error::create_context_failed;
1968 return {};
1969 }
1970 EVP_PKEY_CTX* ctx = nullptr;
1971 if (EVP_DigestSignInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1) {
1972 ec = error::signature_generation_error::signinit_failed;
1973 return {};
1974 }
1975 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
1976 ec = error::signature_generation_error::rsa_padding_failed;
1977 return {};
1978 }
1979// wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
1980// sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
1981#ifndef LIBWOLFSSL_VERSION_HEX
1982 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
1983 ec = error::signature_generation_error::set_rsa_pss_saltlen_failed;
1984 return {};
1985 }
1986#endif
1987 if (EVP_DigestUpdate(md_ctx.get(), data.data(), static_cast<unsigned int>(data.size())) != 1) {
1988 ec = error::signature_generation_error::digestupdate_failed;
1989 return {};
1990 }
1991
1992 size_t size = EVP_PKEY_size(pkey.get());
1993 std::string res(size, 0x00);
1994 if (EVP_DigestSignFinal(
1995 md_ctx.get(),
1996 (unsigned char*)res.data(), // NOLINT(google-readability-casting) requires `const_cast`
1997 &size) <= 0) {
1998 ec = error::signature_generation_error::signfinal_failed;
1999 return {};
2000 }
2001
2002 return res;
2003 }
2004
2011 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
2012 ec.clear();
2013
2014 auto md_ctx = helper::make_evp_md_ctx();
2015 if (!md_ctx) {
2016 ec = error::signature_verification_error::create_context_failed;
2017 return;
2018 }
2019 EVP_PKEY_CTX* ctx = nullptr;
2020 if (EVP_DigestVerifyInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1) {
2021 ec = error::signature_verification_error::verifyinit_failed;
2022 return;
2023 }
2024 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
2025 ec = error::signature_generation_error::rsa_padding_failed;
2026 return;
2027 }
2028// wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
2029// sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
2030#ifndef LIBWOLFSSL_VERSION_HEX
2031 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
2032 ec = error::signature_verification_error::set_rsa_pss_saltlen_failed;
2033 return;
2034 }
2035#endif
2036 if (EVP_DigestUpdate(md_ctx.get(), data.data(), static_cast<unsigned int>(data.size())) != 1) {
2037 ec = error::signature_verification_error::verifyupdate_failed;
2038 return;
2039 }
2040
2041 if (EVP_DigestVerifyFinal(md_ctx.get(), (unsigned char*)signature.data(), signature.size()) <= 0) {
2042 ec = error::signature_verification_error::verifyfinal_failed;
2043 return;
2044 }
2045 }
2050 std::string name() const { return alg_name; }
2051
2052 private:
2056 const EVP_MD* (*md)();
2058 const std::string alg_name;
2059 };
2060
2064 struct hs256 : public hmacsha {
2069 explicit hs256(std::string key) : hmacsha(std::move(key), EVP_sha256, "HS256") {}
2070 };
2074 struct hs384 : public hmacsha {
2079 explicit hs384(std::string key) : hmacsha(std::move(key), EVP_sha384, "HS384") {}
2080 };
2084 struct hs512 : public hmacsha {
2089 explicit hs512(std::string key) : hmacsha(std::move(key), EVP_sha512, "HS512") {}
2090 };
2096 struct rs256 : public rsa {
2105 explicit rs256(const std::string& public_key, const std::string& private_key = "",
2106 const std::string& public_key_password = "", const std::string& private_key_password = "")
2107 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "RS256") {}
2108 };
2112 struct rs384 : public rsa {
2120 explicit rs384(const std::string& public_key, const std::string& private_key = "",
2121 const std::string& public_key_password = "", const std::string& private_key_password = "")
2122 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "RS384") {}
2123 };
2127 struct rs512 : public rsa {
2135 explicit rs512(const std::string& public_key, const std::string& private_key = "",
2136 const std::string& public_key_password = "", const std::string& private_key_password = "")
2137 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "RS512") {}
2138 };
2142 struct es256 : public ecdsa {
2152 explicit es256(const std::string& public_key, const std::string& private_key = "",
2153 const std::string& public_key_password = "", const std::string& private_key_password = "")
2154 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "ES256", 64) {}
2155 };
2159 struct es384 : public ecdsa {
2169 explicit es384(const std::string& public_key, const std::string& private_key = "",
2170 const std::string& public_key_password = "", const std::string& private_key_password = "")
2171 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "ES384", 96) {}
2172 };
2176 struct es512 : public ecdsa {
2186 explicit es512(const std::string& public_key, const std::string& private_key = "",
2187 const std::string& public_key_password = "", const std::string& private_key_password = "")
2188 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "ES512", 132) {}
2189 };
2193 struct es256k : public ecdsa {
2202 explicit es256k(const std::string& public_key, const std::string& private_key = "",
2203 const std::string& public_key_password = "", const std::string& private_key_password = "")
2204 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "ES256K", 64) {}
2205 };
2206
2207#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
2215 struct ed25519 : public eddsa {
2225 explicit ed25519(const std::string& public_key, const std::string& private_key = "",
2226 const std::string& public_key_password = "", const std::string& private_key_password = "")
2227 : eddsa(public_key, private_key, public_key_password, private_key_password, "EdDSA") {}
2228 };
2229
2237 struct ed448 : public eddsa {
2247 explicit ed448(const std::string& public_key, const std::string& private_key = "",
2248 const std::string& public_key_password = "", const std::string& private_key_password = "")
2249 : eddsa(public_key, private_key, public_key_password, private_key_password, "EdDSA") {}
2250 };
2251#endif
2252
2256 struct ps256 : public pss {
2264 explicit ps256(const std::string& public_key, const std::string& private_key = "",
2265 const std::string& public_key_password = "", const std::string& private_key_password = "")
2266 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "PS256") {}
2267 };
2271 struct ps384 : public pss {
2279 explicit ps384(const std::string& public_key, const std::string& private_key = "",
2280 const std::string& public_key_password = "", const std::string& private_key_password = "")
2281 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "PS384") {}
2282 };
2286 struct ps512 : public pss {
2294 explicit ps512(const std::string& public_key, const std::string& private_key = "",
2295 const std::string& public_key_password = "", const std::string& private_key_password = "")
2296 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "PS512") {}
2297 };
2298 } // namespace algorithm
2299
2303 namespace json {
2311 enum class type { boolean, integer, number, string, array, object };
2312 } // namespace json
2313
2314 namespace details {
2315#ifdef __cpp_lib_void_t
2316 template<typename... Ts>
2317 using void_t = std::void_t<Ts...>;
2318#else
2319 // https://en.cppreference.com/w/cpp/types/void_t
2320 template<typename... Ts>
2321 struct make_void {
2322 using type = void;
2323 };
2324
2325 template<typename... Ts>
2326 using void_t = typename make_void<Ts...>::type;
2327#endif
2328
2329#ifdef __cpp_lib_experimental_detect
2330 template<template<typename...> class _Op, typename... _Args>
2331 using is_detected = std::experimental::is_detected<_Op, _Args...>;
2332#else
2333 struct nonesuch {
2334 nonesuch() = delete;
2335 ~nonesuch() = delete;
2336 nonesuch(nonesuch const&) = delete;
2337 nonesuch(nonesuch const&&) = delete;
2338 void operator=(nonesuch const&) = delete;
2339 void operator=(nonesuch&&) = delete;
2340 };
2341
2342 // https://en.cppreference.com/w/cpp/experimental/is_detected
2343 template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
2344 struct detector {
2345 using value = std::false_type;
2346 using type = Default;
2347 };
2348
2349 template<class Default, template<class...> class Op, class... Args>
2350 struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
2351 using value = std::true_type;
2352 using type = Op<Args...>;
2353 };
2354
2355 template<template<class...> class Op, class... Args>
2356 using is_detected = typename detector<nonesuch, void, Op, Args...>::value;
2357#endif
2358
2359 template<typename T, typename Signature>
2360 using is_signature = typename std::is_same<T, Signature>;
2361
2362 template<typename traits_type, template<typename...> class Op, typename Signature>
2363 struct is_function_signature_detected {
2364 using type = Op<traits_type>;
2365 static constexpr auto value = is_detected<Op, traits_type>::value && std::is_function<type>::value &&
2366 is_signature<type, Signature>::value;
2367 };
2368
2369 template<typename traits_type, typename value_type>
2370 struct supports_get_type {
2371 template<typename T>
2372 using get_type_t = decltype(T::get_type);
2373
2374 static constexpr auto value =
2375 is_function_signature_detected<traits_type, get_type_t, json::type(const value_type&)>::value;
2376
2377 // Internal assertions for better feedback
2378 static_assert(value, "traits implementation must provide `jwt::json::type get_type(const value_type&)`");
2379 };
2380
2381#define JWT_CPP_JSON_TYPE_TYPE(TYPE) json_##TYPE_type
2382#define JWT_CPP_AS_TYPE_T(TYPE) as_##TYPE_t
2383#define JWT_CPP_SUPPORTS_AS(TYPE) \
2384 template<typename traits_type, typename value_type, typename JWT_CPP_JSON_TYPE_TYPE(TYPE)> \
2385 struct supports_as_##TYPE { \
2386 template<typename T> \
2387 using JWT_CPP_AS_TYPE_T(TYPE) = decltype(T::as_##TYPE); \
2388 \
2389 static constexpr auto value = \
2390 is_function_signature_detected<traits_type, JWT_CPP_AS_TYPE_T(TYPE), \
2391 JWT_CPP_JSON_TYPE_TYPE(TYPE)(const value_type&)>::value; \
2392 \
2393 static_assert(value, "traits implementation must provide `" #TYPE "_type as_" #TYPE "(const value_type&)`"); \
2394 }
2395
2396 JWT_CPP_SUPPORTS_AS(object);
2397 JWT_CPP_SUPPORTS_AS(array);
2398 JWT_CPP_SUPPORTS_AS(string);
2399 JWT_CPP_SUPPORTS_AS(number);
2400 JWT_CPP_SUPPORTS_AS(integer);
2401 JWT_CPP_SUPPORTS_AS(boolean);
2402
2403#undef JWT_CPP_JSON_TYPE_TYPE
2404#undef JWT_CPP_AS_TYPE_T
2405#undef JWT_CPP_SUPPORTS_AS
2406
2407 template<typename traits>
2408 struct is_valid_traits {
2409 static constexpr auto value =
2410 supports_get_type<traits, typename traits::value_type>::value &&
2411 supports_as_object<traits, typename traits::value_type, typename traits::object_type>::value &&
2412 supports_as_array<traits, typename traits::value_type, typename traits::array_type>::value &&
2413 supports_as_string<traits, typename traits::value_type, typename traits::string_type>::value &&
2414 supports_as_number<traits, typename traits::value_type, typename traits::number_type>::value &&
2415 supports_as_integer<traits, typename traits::value_type, typename traits::integer_type>::value &&
2416 supports_as_boolean<traits, typename traits::value_type, typename traits::boolean_type>::value;
2417 };
2418
2419 template<typename value_type>
2420 struct is_valid_json_value {
2421 static constexpr auto value =
2422 std::is_default_constructible<value_type>::value &&
2423 std::is_constructible<value_type, const value_type&>::value && // a more generic is_copy_constructible
2424 std::is_move_constructible<value_type>::value && std::is_assignable<value_type, value_type>::value &&
2425 std::is_copy_assignable<value_type>::value && std::is_move_assignable<value_type>::value;
2426 // TODO(prince-chrismc): Stream operators
2427 };
2428
2429 // https://stackoverflow.com/a/53967057/8480874
2430 template<typename T, typename = void>
2431 struct is_iterable : std::false_type {};
2432
2433 template<typename T>
2434 struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>())),
2435#if __cplusplus > 201402L
2436 decltype(std::cbegin(std::declval<T>())), decltype(std::cend(std::declval<T>()))
2437#else
2438 decltype(std::begin(std::declval<const T>())),
2439 decltype(std::end(std::declval<const T>()))
2440#endif
2441 >> : std::true_type {
2442 };
2443
2444#if __cplusplus > 201703L
2445 template<typename T>
2446 inline constexpr bool is_iterable_v = is_iterable<T>::value;
2447#endif
2448
2449 template<typename object_type, typename string_type>
2450 using is_count_signature = typename std::is_integral<decltype(std::declval<const object_type>().count(
2451 std::declval<const string_type>()))>;
2452
2453 template<typename object_type, typename string_type, typename = void>
2454 struct is_subcription_operator_signature : std::false_type {};
2455
2456 template<typename object_type, typename string_type>
2457 struct is_subcription_operator_signature<
2458 object_type, string_type,
2459 void_t<decltype(std::declval<object_type>().operator[](std::declval<string_type>()))>> : std::true_type {
2460 // TODO(prince-chrismc): I am not convienced this is meaningful anymore
2461 static_assert(
2462 value,
2463 "object_type must implementate the subscription operator '[]' taking string_type as an argument");
2464 };
2465
2466 template<typename object_type, typename value_type, typename string_type>
2467 using is_at_const_signature =
2468 typename std::is_same<decltype(std::declval<const object_type>().at(std::declval<const string_type>())),
2469 const value_type&>;
2470
2471 template<typename value_type, typename string_type, typename object_type>
2472 struct is_valid_json_object {
2473 template<typename T>
2474 using mapped_type_t = typename T::mapped_type;
2475 template<typename T>
2476 using key_type_t = typename T::key_type;
2477 template<typename T>
2478 using iterator_t = typename T::iterator;
2479 template<typename T>
2480 using const_iterator_t = typename T::const_iterator;
2481
2482 static constexpr auto value =
2483 std::is_constructible<value_type, object_type>::value &&
2484 is_detected<mapped_type_t, object_type>::value &&
2485 std::is_same<typename object_type::mapped_type, value_type>::value &&
2486 is_detected<key_type_t, object_type>::value &&
2487 (std::is_same<typename object_type::key_type, string_type>::value ||
2488 std::is_constructible<typename object_type::key_type, string_type>::value) &&
2489 is_detected<iterator_t, object_type>::value && is_detected<const_iterator_t, object_type>::value &&
2490 is_iterable<object_type>::value && is_count_signature<object_type, string_type>::value &&
2491 is_subcription_operator_signature<object_type, string_type>::value &&
2492 is_at_const_signature<object_type, value_type, string_type>::value;
2493 };
2494
2495 template<typename value_type, typename array_type>
2496 struct is_valid_json_array {
2497 template<typename T>
2498 using value_type_t = typename T::value_type;
2499 using front_base_type = typename std::decay<decltype(std::declval<array_type>().front())>::type;
2500
2501 static constexpr auto value = std::is_constructible<value_type, array_type>::value &&
2502 is_iterable<array_type>::value &&
2503 is_detected<value_type_t, array_type>::value &&
2504 std::is_same<typename array_type::value_type, value_type>::value &&
2505 std::is_same<front_base_type, value_type>::value;
2506 };
2507
2508 template<typename string_type, typename integer_type>
2509 using is_substr_start_end_index_signature =
2510 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>(),
2511 std::declval<integer_type>())),
2512 string_type>;
2513
2514 template<typename string_type, typename integer_type>
2515 using is_substr_start_index_signature =
2516 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>())),
2517 string_type>;
2518
2519 template<typename string_type>
2520 using is_std_operate_plus_signature =
2521 typename std::is_same<decltype(std::operator+(std::declval<string_type>(), std::declval<string_type>())),
2522 string_type>;
2523
2524 template<typename value_type, typename string_type, typename integer_type>
2525 struct is_valid_json_string {
2526 static constexpr auto substr = is_substr_start_end_index_signature<string_type, integer_type>::value &&
2527 is_substr_start_index_signature<string_type, integer_type>::value;
2528 static_assert(substr, "string_type must have a substr method taking only a start index and an overload "
2529 "taking a start and end index, both must return a string_type");
2530
2531 static constexpr auto operator_plus = is_std_operate_plus_signature<string_type>::value;
2532 static_assert(operator_plus,
2533 "string_type must have a '+' operator implemented which returns the concatenated string");
2534
2535 static constexpr auto value =
2536 std::is_constructible<value_type, string_type>::value && substr && operator_plus;
2537 };
2538
2539 template<typename value_type, typename number_type>
2540 struct is_valid_json_number {
2541 static constexpr auto value =
2542 std::is_floating_point<number_type>::value && std::is_constructible<value_type, number_type>::value;
2543 };
2544
2545 template<typename value_type, typename integer_type>
2546 struct is_valid_json_integer {
2547 static constexpr auto value = std::is_signed<integer_type>::value &&
2548 !std::is_floating_point<integer_type>::value &&
2549 std::is_constructible<value_type, integer_type>::value;
2550 };
2551 template<typename value_type, typename boolean_type>
2552 struct is_valid_json_boolean {
2553 static constexpr auto value = std::is_convertible<boolean_type, bool>::value &&
2554 std::is_constructible<value_type, boolean_type>::value;
2555 };
2556
2557 template<typename value_type, typename object_type, typename array_type, typename string_type,
2558 typename number_type, typename integer_type, typename boolean_type>
2559 struct is_valid_json_types {
2560 // Internal assertions for better feedback
2561 static_assert(is_valid_json_value<value_type>::value,
2562 "value_type must meet basic requirements, default constructor, copyable, moveable");
2563 static_assert(is_valid_json_object<value_type, string_type, object_type>::value,
2564 "object_type must be a string_type to value_type container");
2565 static_assert(is_valid_json_array<value_type, array_type>::value,
2566 "array_type must be a container of value_type");
2567
2568 static constexpr auto value = is_valid_json_value<value_type>::value &&
2569 is_valid_json_object<value_type, string_type, object_type>::value &&
2570 is_valid_json_array<value_type, array_type>::value &&
2571 is_valid_json_string<value_type, string_type, integer_type>::value &&
2572 is_valid_json_number<value_type, number_type>::value &&
2573 is_valid_json_integer<value_type, integer_type>::value &&
2574 is_valid_json_boolean<value_type, boolean_type>::value;
2575 };
2576 } // namespace details
2577
2585 template<typename json_traits>
2593 static_assert(std::is_same<typename json_traits::string_type, std::string>::value ||
2594 std::is_convertible<typename json_traits::string_type, std::string>::value ||
2595 std::is_constructible<typename json_traits::string_type, std::string>::value,
2596 "string_type must be a std::string, convertible to a std::string, or construct a std::string.");
2597
2598 static_assert(
2599 details::is_valid_json_types<typename json_traits::value_type, typename json_traits::object_type,
2600 typename json_traits::array_type, typename json_traits::string_type,
2601 typename json_traits::number_type, typename json_traits::integer_type,
2602 typename json_traits::boolean_type>::value,
2603 "must satisfy json container requirements");
2604 static_assert(details::is_valid_traits<json_traits>::value, "traits must satisfy requirements");
2605
2606 typename json_traits::value_type val;
2607
2608 public:
2612 using set_t = std::set<typename json_traits::string_type>;
2613
2614 basic_claim() = default;
2615 basic_claim(const basic_claim&) = default;
2616 basic_claim(basic_claim&&) = default;
2617 basic_claim& operator=(const basic_claim&) = default;
2618 basic_claim& operator=(basic_claim&&) = default;
2619 ~basic_claim() = default;
2620
2621 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s) : val(std::move(s)) {}
2622 JWT_CLAIM_EXPLICIT basic_claim(const date& d)
2623 : val(typename json_traits::integer_type(
2624 std::chrono::duration_cast<std::chrono::seconds>(d.time_since_epoch()).count())) {}
2625 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a) : val(std::move(a)) {}
2626 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v) : val(std::move(v)) {}
2627 JWT_CLAIM_EXPLICIT basic_claim(const set_t& s) : val(typename json_traits::array_type(s.begin(), s.end())) {}
2628 template<typename Iterator>
2629 basic_claim(Iterator begin, Iterator end) : val(typename json_traits::array_type(begin, end)) {}
2630
2635 typename json_traits::value_type to_json() const { return val; }
2636
2641 std::istream& operator>>(std::istream& is) { return is >> val; }
2642
2647 std::ostream& operator<<(std::ostream& os) { return os << val; }
2648
2654 json::type get_type() const { return json_traits::get_type(val); }
2655
2661 typename json_traits::string_type as_string() const { return json_traits::as_string(val); }
2662
2671 date as_date() const {
2672 using std::chrono::system_clock;
2673 if (get_type() == json::type::number)
2674 return date(std::chrono::seconds(static_cast<int64_t>(std::llround(as_number()))));
2675 return date(std::chrono::seconds(as_integer()));
2676 }
2677
2683 typename json_traits::array_type as_array() const { return json_traits::as_array(val); }
2684
2690 set_t as_set() const {
2691 set_t res;
2692 for (const auto& e : json_traits::as_array(val)) {
2693 res.insert(json_traits::as_string(e));
2694 }
2695 return res;
2696 }
2697
2703 typename json_traits::integer_type as_integer() const { return json_traits::as_integer(val); }
2704
2710 typename json_traits::boolean_type as_boolean() const { return json_traits::as_boolean(val); }
2711
2717 typename json_traits::number_type as_number() const { return json_traits::as_number(val); }
2718 };
2719
2720 namespace error {
2724 struct invalid_json_exception : public std::runtime_error {
2725 invalid_json_exception() : runtime_error("invalid json") {}
2726 };
2730 struct claim_not_present_exception : public std::out_of_range {
2731 claim_not_present_exception() : out_of_range("claim not found") {}
2732 };
2733 } // namespace error
2734
2735 namespace details {
2736 template<typename json_traits>
2737 struct map_of_claims {
2738 typename json_traits::object_type claims;
2739 using basic_claim_t = basic_claim<json_traits>;
2740 using iterator = typename json_traits::object_type::iterator;
2741 using const_iterator = typename json_traits::object_type::const_iterator;
2742
2743 map_of_claims() = default;
2744 map_of_claims(const map_of_claims&) = default;
2745 map_of_claims(map_of_claims&&) = default;
2746 map_of_claims& operator=(const map_of_claims&) = default;
2747 map_of_claims& operator=(map_of_claims&&) = default;
2748
2749 map_of_claims(typename json_traits::object_type json) : claims(std::move(json)) {}
2750
2751 iterator begin() { return claims.begin(); }
2752 iterator end() { return claims.end(); }
2753 const_iterator cbegin() const { return claims.begin(); }
2754 const_iterator cend() const { return claims.end(); }
2755 const_iterator begin() const { return claims.begin(); }
2756 const_iterator end() const { return claims.end(); }
2757
2766 static typename json_traits::object_type parse_claims(const typename json_traits::string_type& str) {
2767 typename json_traits::value_type val;
2768 if (!json_traits::parse(val, str)) throw error::invalid_json_exception();
2769
2770 return json_traits::as_object(val);
2771 };
2772
2777 bool has_claim(const typename json_traits::string_type& name) const noexcept {
2778 return claims.count(name) != 0;
2779 }
2780
2788 basic_claim_t get_claim(const typename json_traits::string_type& name) const {
2789 if (!has_claim(name)) throw error::claim_not_present_exception();
2790 return basic_claim_t{claims.at(name)};
2791 }
2792 };
2793 } // namespace details
2794
2799 template<typename json_traits>
2800 class payload {
2801 protected:
2802 details::map_of_claims<json_traits> payload_claims;
2803
2804 public:
2806
2811 bool has_issuer() const noexcept { return has_payload_claim("iss"); }
2816 bool has_subject() const noexcept { return has_payload_claim("sub"); }
2821 bool has_audience() const noexcept { return has_payload_claim("aud"); }
2826 bool has_expires_at() const noexcept { return has_payload_claim("exp"); }
2831 bool has_not_before() const noexcept { return has_payload_claim("nbf"); }
2836 bool has_issued_at() const noexcept { return has_payload_claim("iat"); }
2841 bool has_id() const noexcept { return has_payload_claim("jti"); }
2848 typename json_traits::string_type get_issuer() const { return get_payload_claim("iss").as_string(); }
2855 typename json_traits::string_type get_subject() const { return get_payload_claim("sub").as_string(); }
2863 auto aud = get_payload_claim("aud");
2864 if (aud.get_type() == json::type::string) return {aud.as_string()};
2865
2866 return aud.as_set();
2867 }
2874 date get_expires_at() const { return get_payload_claim("exp").as_date(); }
2881 date get_not_before() const { return get_payload_claim("nbf").as_date(); }
2888 date get_issued_at() const { return get_payload_claim("iat").as_date(); }
2895 typename json_traits::string_type get_id() const { return get_payload_claim("jti").as_string(); }
2900 bool has_payload_claim(const typename json_traits::string_type& name) const noexcept {
2901 return payload_claims.has_claim(name);
2902 }
2908 basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const {
2909 return payload_claims.get_claim(name);
2910 }
2911 };
2912
2917 template<typename json_traits>
2918 class header {
2919 protected:
2920 details::map_of_claims<json_traits> header_claims;
2921
2922 public:
2928 bool has_algorithm() const noexcept { return has_header_claim("alg"); }
2933 bool has_type() const noexcept { return has_header_claim("typ"); }
2938 bool has_content_type() const noexcept { return has_header_claim("cty"); }
2943 bool has_key_id() const noexcept { return has_header_claim("kid"); }
2950 typename json_traits::string_type get_algorithm() const { return get_header_claim("alg").as_string(); }
2957 typename json_traits::string_type get_type() const { return get_header_claim("typ").as_string(); }
2964 typename json_traits::string_type get_content_type() const { return get_header_claim("cty").as_string(); }
2971 typename json_traits::string_type get_key_id() const { return get_header_claim("kid").as_string(); }
2976 bool has_header_claim(const typename json_traits::string_type& name) const noexcept {
2977 return header_claims.has_claim(name);
2978 }
2984 basic_claim_t get_header_claim(const typename json_traits::string_type& name) const {
2985 return header_claims.get_claim(name);
2986 }
2987 };
2988
2992 template<typename json_traits>
2993 class decoded_jwt : public header<json_traits>, public payload<json_traits> {
2994 protected:
2996 typename json_traits::string_type token;
2998 typename json_traits::string_type header;
3000 typename json_traits::string_type header_base64;
3002 typename json_traits::string_type payload;
3004 typename json_traits::string_type payload_base64;
3006 typename json_traits::string_type signature;
3008 typename json_traits::string_type signature_base64;
3009
3010 public:
3012#ifndef JWT_DISABLE_BASE64
3022 JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type& token)
3023 : decoded_jwt(token, [](const typename json_traits::string_type& str) {
3024 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(str));
3025 }) {}
3026#endif
3038 template<typename Decode>
3039 decoded_jwt(const typename json_traits::string_type& token, Decode decode) : token(token) {
3040 auto hdr_end = token.find('.');
3041 if (hdr_end == json_traits::string_type::npos) throw std::invalid_argument("invalid token supplied");
3042 auto payload_end = token.find('.', hdr_end + 1);
3043 if (payload_end == json_traits::string_type::npos) throw std::invalid_argument("invalid token supplied");
3044 header_base64 = token.substr(0, hdr_end);
3045 payload_base64 = token.substr(hdr_end + 1, payload_end - hdr_end - 1);
3046 signature_base64 = token.substr(payload_end + 1);
3047
3051
3052 this->header_claims = details::map_of_claims<json_traits>::parse_claims(header);
3053 this->payload_claims = details::map_of_claims<json_traits>::parse_claims(payload);
3054 }
3055
3060 const typename json_traits::string_type& get_token() const noexcept { return token; }
3065 const typename json_traits::string_type& get_header() const noexcept { return header; }
3070 const typename json_traits::string_type& get_payload() const noexcept { return payload; }
3075 const typename json_traits::string_type& get_signature() const noexcept { return signature; }
3080 const typename json_traits::string_type& get_header_base64() const noexcept { return header_base64; }
3085 const typename json_traits::string_type& get_payload_base64() const noexcept { return payload_base64; }
3090 const typename json_traits::string_type& get_signature_base64() const noexcept { return signature_base64; }
3095 typename json_traits::object_type get_payload_json() const { return this->payload_claims.claims; }
3100 typename json_traits::object_type get_header_json() const { return this->header_claims.claims; }
3108 basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const {
3109 return this->payload_claims.get_claim(name);
3110 }
3118 basic_claim_t get_header_claim(const typename json_traits::string_type& name) const {
3119 return this->header_claims.get_claim(name);
3120 }
3121 };
3122
3127 template<typename Clock, typename json_traits>
3128 class builder {
3129 typename json_traits::object_type header_claims;
3130 typename json_traits::object_type payload_claims;
3131
3133 Clock clock;
3134
3135 public:
3140 JWT_CLAIM_EXPLICIT builder(Clock c) : clock(c) {}
3147 builder& set_header_claim(const typename json_traits::string_type& id, typename json_traits::value_type c) {
3148 header_claims[id] = std::move(c);
3149 return *this;
3150 }
3151
3158 builder& set_header_claim(const typename json_traits::string_type& id, basic_claim<json_traits> c) {
3159 header_claims[id] = c.to_json();
3160 return *this;
3161 }
3168 builder& set_payload_claim(const typename json_traits::string_type& id, typename json_traits::value_type c) {
3169 payload_claims[id] = std::move(c);
3170 return *this;
3171 }
3178 builder& set_payload_claim(const typename json_traits::string_type& id, basic_claim<json_traits> c) {
3179 payload_claims[id] = c.to_json();
3180 return *this;
3181 }
3189 builder& set_algorithm(typename json_traits::string_type str) {
3190 return set_header_claim("alg", typename json_traits::value_type(str));
3191 }
3197 builder& set_type(typename json_traits::string_type str) {
3198 return set_header_claim("typ", typename json_traits::value_type(str));
3199 }
3205 builder& set_content_type(typename json_traits::string_type str) {
3206 return set_header_claim("cty", typename json_traits::value_type(str));
3207 }
3214 builder& set_key_id(typename json_traits::string_type str) {
3215 return set_header_claim("kid", typename json_traits::value_type(str));
3216 }
3222 builder& set_issuer(typename json_traits::string_type str) {
3223 return set_payload_claim("iss", typename json_traits::value_type(str));
3224 }
3230 builder& set_subject(typename json_traits::string_type str) {
3231 return set_payload_claim("sub", typename json_traits::value_type(str));
3232 }
3238 builder& set_audience(typename json_traits::array_type a) {
3239 return set_payload_claim("aud", typename json_traits::value_type(a));
3240 }
3246 builder& set_audience(typename json_traits::string_type aud) {
3247 return set_payload_claim("aud", typename json_traits::value_type(aud));
3248 }
3260 template<class Rep, class Period>
3261 builder& set_expires_in(const std::chrono::duration<Rep, Period>& d) {
3262 return set_payload_claim("exp", basic_claim<json_traits>(clock.now() + d));
3263 }
3280 builder& set_issued_now() { return set_issued_at(clock.now()); }
3286 builder& set_id(const typename json_traits::string_type& str) {
3287 return set_payload_claim("jti", typename json_traits::value_type(str));
3288 }
3289
3301 template<typename Algo, typename Encode>
3302 typename json_traits::string_type sign(const Algo& algo, Encode encode) const {
3303 std::error_code ec;
3304 auto res = sign(algo, encode, ec);
3306 return res;
3307 }
3308#ifndef JWT_DISABLE_BASE64
3317 template<typename Algo>
3318 typename json_traits::string_type sign(const Algo& algo) const {
3319 std::error_code ec;
3320 auto res = sign(algo, ec);
3322 return res;
3323 }
3324#endif
3325
3338 template<typename Algo, typename Encode>
3339 typename json_traits::string_type sign(const Algo& algo, Encode encode, std::error_code& ec) const {
3340 // make a copy such that a builder can be re-used
3341 typename json_traits::object_type obj_header = header_claims;
3342 if (header_claims.count("alg") == 0) obj_header["alg"] = typename json_traits::value_type(algo.name());
3343
3344 const auto header = encode(json_traits::serialize(typename json_traits::value_type(obj_header)));
3345 const auto payload = encode(json_traits::serialize(typename json_traits::value_type(payload_claims)));
3346 const auto token = header + "." + payload;
3347
3348 auto signature = algo.sign(token, ec);
3349 if (ec) return {};
3350
3351 return token + "." + encode(signature);
3352 }
3353#ifndef JWT_DISABLE_BASE64
3363 template<typename Algo>
3364 typename json_traits::string_type sign(const Algo& algo, std::error_code& ec) const {
3365 return sign(
3366 algo,
3367 [](const typename json_traits::string_type& data) {
3368 return base::trim<alphabet::base64url>(base::encode<alphabet::base64url>(data));
3369 },
3370 ec);
3371 }
3372#endif
3373 };
3374
3375 namespace verify_ops {
3379 template<typename json_traits>
3381 verify_context(date ctime, const decoded_jwt<json_traits>& j, size_t l)
3382 : current_time(ctime), jwt(j), default_leeway(l) {}
3389
3391 typename json_traits::string_type claim_key{};
3392
3399 basic_claim<json_traits> get_claim(bool in_header, std::error_code& ec) const {
3400 if (in_header) {
3401 if (!jwt.has_header_claim(claim_key)) {
3402 ec = error::token_verification_error::missing_claim;
3403 return {};
3404 }
3405 return jwt.get_header_claim(claim_key);
3406 } else {
3407 if (!jwt.has_payload_claim(claim_key)) {
3408 ec = error::token_verification_error::missing_claim;
3409 return {};
3410 }
3411 return jwt.get_payload_claim(claim_key);
3412 }
3413 }
3421 basic_claim<json_traits> get_claim(bool in_header, json::type t, std::error_code& ec) const {
3422 auto c = get_claim(in_header, ec);
3423 if (ec) return {};
3424 if (c.get_type() != t) {
3425 ec = error::token_verification_error::claim_type_missmatch;
3426 return {};
3427 }
3428 return c;
3429 }
3435 basic_claim<json_traits> get_claim(std::error_code& ec) const { return get_claim(false, ec); }
3442 basic_claim<json_traits> get_claim(json::type t, std::error_code& ec) const {
3443 return get_claim(false, t, ec);
3444 }
3445 };
3446
3450 template<typename json_traits, bool in_header = false>
3452 const basic_claim<json_traits> expected;
3453 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3454 auto jc = ctx.get_claim(in_header, expected.get_type(), ec);
3455 if (ec) return;
3456 const bool matches = [&]() {
3457 switch (expected.get_type()) {
3458 case json::type::boolean: return expected.as_boolean() == jc.as_boolean();
3459 case json::type::integer: return expected.as_integer() == jc.as_integer();
3460 case json::type::number: return expected.as_number() == jc.as_number();
3461 case json::type::string: return expected.as_string() == jc.as_string();
3462 case json::type::array:
3463 case json::type::object:
3464 return json_traits::serialize(expected.to_json()) == json_traits::serialize(jc.to_json());
3465 default: throw std::logic_error("internal error, should be unreachable");
3466 }
3467 }();
3468 if (!matches) {
3469 ec = error::token_verification_error::claim_value_missmatch;
3470 return;
3471 }
3472 }
3473 };
3474
3479 template<typename json_traits, bool in_header = false>
3481 const size_t leeway;
3482 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3483 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3484 if (ec) return;
3485 auto c = jc.as_date();
3486 if (ctx.current_time > c + std::chrono::seconds(leeway)) {
3487 ec = error::token_verification_error::token_expired;
3488 }
3489 }
3490 };
3491
3496 template<typename json_traits, bool in_header = false>
3498 const size_t leeway;
3499 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3500 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3501 if (ec) return;
3502 auto c = jc.as_date();
3503 if (ctx.current_time < c - std::chrono::seconds(leeway)) {
3504 ec = error::token_verification_error::token_expired;
3505 }
3506 }
3507 };
3508
3514 template<typename json_traits, bool in_header = false>
3516 const typename basic_claim<json_traits>::set_t expected;
3517 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3518 auto c = ctx.get_claim(in_header, ec);
3519 if (ec) return;
3520 if (c.get_type() == json::type::string) {
3521 if (expected.size() != 1 || *expected.begin() != c.as_string()) {
3522 ec = error::token_verification_error::audience_missmatch;
3523 return;
3524 }
3525 } else if (c.get_type() == json::type::array) {
3526 auto jc = c.as_set();
3527 for (auto& e : expected) {
3528 if (jc.find(e) == jc.end()) {
3529 ec = error::token_verification_error::audience_missmatch;
3530 return;
3531 }
3532 }
3533 } else {
3534 ec = error::token_verification_error::claim_type_missmatch;
3535 return;
3536 }
3537 }
3538 };
3539
3543 template<typename json_traits, bool in_header = false>
3545 const typename json_traits::string_type expected;
3546 std::locale locale;
3547 insensitive_string_claim(const typename json_traits::string_type& e, std::locale loc)
3548 : expected(to_lower_unicode(e, loc)), locale(loc) {}
3549
3550 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3551 const auto c = ctx.get_claim(in_header, json::type::string, ec);
3552 if (ec) return;
3553 if (to_lower_unicode(c.as_string(), locale) != expected) {
3554 ec = error::token_verification_error::claim_value_missmatch;
3555 }
3556 }
3557
3558 static std::string to_lower_unicode(const std::string& str, const std::locale& loc) {
3559 std::mbstate_t state = std::mbstate_t();
3560 const char* in_next = str.data();
3561 const char* in_end = str.data() + str.size();
3562 std::wstring wide;
3563 wide.reserve(str.size());
3564
3565 while (in_next != in_end) {
3566 wchar_t wc;
3567 std::size_t result = std::mbrtowc(&wc, in_next, in_end - in_next, &state);
3568 if (result == static_cast<std::size_t>(-1)) {
3569 throw std::runtime_error("encoding error: " + std::string(std::strerror(errno)));
3570 } else if (result == static_cast<std::size_t>(-2)) {
3571 throw std::runtime_error("conversion error: next bytes constitute an incomplete, but so far "
3572 "valid, multibyte character.");
3573 }
3574 in_next += result;
3575 wide.push_back(wc);
3576 }
3577
3578 auto& f = std::use_facet<std::ctype<wchar_t>>(loc);
3579 f.tolower(&wide[0], &wide[0] + wide.size());
3580
3581 std::string out;
3582 out.reserve(wide.size());
3583 for (wchar_t wc : wide) {
3584 char mb[MB_LEN_MAX];
3585 std::size_t n = std::wcrtomb(mb, wc, &state);
3586 if (n != static_cast<std::size_t>(-1)) out.append(mb, n);
3587 }
3588
3589 return out;
3590 }
3591 };
3592 } // namespace verify_ops
3593
3598 template<typename Clock, typename json_traits>
3599 class verifier {
3600 public:
3612 std::function<void(const verify_ops::verify_context<json_traits>&, std::error_code& ec)>;
3613
3614 private:
3615 struct algo_base {
3616 virtual ~algo_base() = default;
3617 virtual void verify(const std::string& data, const std::string& sig, std::error_code& ec) = 0;
3618 };
3619 template<typename T>
3620 struct algo : public algo_base {
3621 T alg;
3622 explicit algo(T a) : alg(a) {}
3623 void verify(const std::string& data, const std::string& sig, std::error_code& ec) override {
3624 alg.verify(data, sig, ec);
3625 }
3626 };
3628 std::unordered_map<typename json_traits::string_type, verify_check_fn_t> claims;
3630 size_t default_leeway = 0;
3632 Clock clock;
3634 std::unordered_map<std::string, std::shared_ptr<algo_base>> algs;
3635
3636 public:
3641 explicit verifier(Clock c) : clock(c) {
3642 claims["exp"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3643 if (!ctx.jwt.has_expires_at()) return;
3644 auto exp = ctx.jwt.get_expires_at();
3645 if (ctx.current_time > exp + std::chrono::seconds(ctx.default_leeway)) {
3646 ec = error::token_verification_error::token_expired;
3647 }
3648 };
3649 claims["iat"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3650 if (!ctx.jwt.has_issued_at()) return;
3651 auto iat = ctx.jwt.get_issued_at();
3652 if (ctx.current_time < iat - std::chrono::seconds(ctx.default_leeway)) {
3653 ec = error::token_verification_error::token_expired;
3654 }
3655 };
3656 claims["nbf"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3657 if (!ctx.jwt.has_not_before()) return;
3658 auto nbf = ctx.jwt.get_not_before();
3659 if (ctx.current_time < nbf - std::chrono::seconds(ctx.default_leeway)) {
3660 ec = error::token_verification_error::token_expired;
3661 }
3662 };
3663 }
3664
3671 default_leeway = leeway;
3672 return *this;
3673 }
3682 return *this;
3683 }
3692 return *this;
3693 }
3702 return *this;
3703 }
3704
3716 verifier& with_type(const typename json_traits::string_type& type, std::locale locale = std::locale{}) {
3717 return with_claim("typ", verify_ops::insensitive_string_claim<json_traits, true>{type, std::move(locale)});
3718 }
3719
3726 verifier& with_issuer(const typename json_traits::string_type& iss) {
3727 return with_claim("iss", basic_claim_t(iss));
3728 }
3729
3736 verifier& with_subject(const typename json_traits::string_type& sub) {
3737 return with_claim("sub", basic_claim_t(sub));
3738 }
3746 claims["aud"] = verify_ops::is_subset_claim<json_traits>{aud};
3747 return *this;
3748 }
3755 verifier& with_audience(const typename json_traits::string_type& aud) {
3756 typename basic_claim_t::set_t s;
3757 s.insert(aud);
3758 return with_audience(s);
3759 }
3766 verifier& with_id(const typename json_traits::string_type& id) { return with_claim("jti", basic_claim_t(id)); }
3767
3779 verifier& with_claim(const typename json_traits::string_type& name, verify_check_fn_t fn) {
3780 claims[name] = fn;
3781 return *this;
3782 }
3783
3794 verifier& with_claim(const typename json_traits::string_type& name, basic_claim_t c) {
3796 }
3797
3811 template<typename Algorithm>
3812 verifier& allow_algorithm(Algorithm alg) {
3813 algs[alg.name()] = std::make_shared<algo<Algorithm>>(alg);
3814 return *this;
3815 }
3816
3823 std::error_code ec;
3824 verify(jwt, ec);
3826 }
3832 void verify(const decoded_jwt<json_traits>& jwt, std::error_code& ec) const {
3833 ec.clear();
3834 const typename json_traits::string_type data = jwt.get_header_base64() + "." + jwt.get_payload_base64();
3835 const typename json_traits::string_type sig = jwt.get_signature();
3836 const std::string algo = jwt.get_algorithm();
3837 if (algs.count(algo) == 0) {
3838 ec = error::token_verification_error::wrong_algorithm;
3839 return;
3840 }
3841 algs.at(algo)->verify(data, sig, ec);
3842 if (ec) return;
3843
3844 verify_ops::verify_context<json_traits> ctx{clock.now(), jwt, default_leeway};
3845 for (auto& c : claims) {
3846 ctx.claim_key = c.first;
3847 c.second(ctx, ec);
3848 if (ec) return;
3849 }
3850 }
3851 };
3852
3861 template<typename json_traits>
3862 class jwk {
3864 const details::map_of_claims<json_traits> jwk_claims;
3865
3866 public:
3867 JWT_CLAIM_EXPLICIT jwk(const typename json_traits::string_type& str)
3868 : jwk_claims(details::map_of_claims<json_traits>::parse_claims(str)) {}
3869
3870 JWT_CLAIM_EXPLICIT jwk(const typename json_traits::value_type& json)
3871 : jwk_claims(json_traits::as_object(json)) {}
3872
3881 typename json_traits::string_type get_key_type() const { return get_jwk_claim("kty").as_string(); }
3882
3889 typename json_traits::string_type get_use() const { return get_jwk_claim("use").as_string(); }
3890
3897 typename basic_claim_t::set_t get_key_operations() const { return get_jwk_claim("key_ops").as_set(); }
3898
3905 typename json_traits::string_type get_algorithm() const { return get_jwk_claim("alg").as_string(); }
3906
3913 typename json_traits::string_type get_key_id() const { return get_jwk_claim("kid").as_string(); }
3914
3925 typename json_traits::string_type get_curve() const { return get_jwk_claim("crv").as_string(); }
3926
3933 typename json_traits::array_type get_x5c() const { return get_jwk_claim("x5c").as_array(); };
3934
3941 typename json_traits::string_type get_x5u() const { return get_jwk_claim("x5u").as_string(); };
3942
3949 typename json_traits::string_type get_x5t() const { return get_jwk_claim("x5t").as_string(); };
3950
3957 typename json_traits::string_type get_x5t_sha256() const { return get_jwk_claim("x5t#S256").as_string(); };
3958
3965 typename json_traits::string_type get_x5c_key_value() const {
3966 auto x5c_array = get_jwk_claim("x5c").as_array();
3967 if (x5c_array.size() == 0) throw error::claim_not_present_exception();
3968
3969 return json_traits::as_string(x5c_array.front());
3970 };
3971
3976 bool has_key_type() const noexcept { return has_jwk_claim("kty"); }
3977
3982 bool has_use() const noexcept { return has_jwk_claim("use"); }
3983
3988 bool has_key_operations() const noexcept { return has_jwk_claim("key_ops"); }
3989
3994 bool has_algorithm() const noexcept { return has_jwk_claim("alg"); }
3995
4000 bool has_curve() const noexcept { return has_jwk_claim("crv"); }
4001
4006 bool has_key_id() const noexcept { return has_jwk_claim("kid"); }
4007
4012 bool has_x5u() const noexcept { return has_jwk_claim("x5u"); }
4013
4018 bool has_x5c() const noexcept { return has_jwk_claim("x5c"); }
4019
4024 bool has_x5t() const noexcept { return has_jwk_claim("x5t"); }
4025
4030 bool has_x5t_sha256() const noexcept { return has_jwk_claim("x5t#S256"); }
4031
4036 bool has_jwk_claim(const typename json_traits::string_type& name) const noexcept {
4037 return jwk_claims.has_claim(name);
4038 }
4039
4045 basic_claim_t get_jwk_claim(const typename json_traits::string_type& name) const {
4046 return jwk_claims.get_claim(name);
4047 }
4048
4053 bool empty() const noexcept { return jwk_claims.empty(); }
4054
4059 typename json_traits::object_type get_claims() const { return this->jwk_claims.claims; }
4060 };
4061
4072 template<typename json_traits>
4073 class jwks {
4074 public:
4078 using jwks_vector_t = std::vector<jwks_t>;
4079 using iterator = typename jwks_vector_t::iterator;
4080 using const_iterator = typename jwks_vector_t::const_iterator;
4081
4085 jwks() = default;
4086
4093 JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type& str) {
4094 typename json_traits::value_type parsed_val;
4095 if (!json_traits::parse(parsed_val, str)) throw error::invalid_json_exception();
4096
4097 const details::map_of_claims<json_traits> jwks_json = json_traits::as_object(parsed_val);
4098 if (!jwks_json.has_claim("keys")) throw error::invalid_json_exception();
4099
4100 auto jwk_list = jwks_json.get_claim("keys").as_array();
4101 std::transform(jwk_list.begin(), jwk_list.end(), std::back_inserter(jwk_claims),
4102 [](const typename json_traits::value_type& val) { return jwks_t{val}; });
4103 }
4104
4105 iterator begin() { return jwk_claims.begin(); }
4106 iterator end() { return jwk_claims.end(); }
4107 const_iterator cbegin() const { return jwk_claims.begin(); }
4108 const_iterator cend() const { return jwk_claims.end(); }
4109 const_iterator begin() const { return jwk_claims.begin(); }
4110 const_iterator end() const { return jwk_claims.end(); }
4111
4116 bool has_jwk(const typename json_traits::string_type& key_id) const noexcept {
4117 return find_by_kid(key_id) != end();
4118 }
4119
4125 jwks_t get_jwk(const typename json_traits::string_type& key_id) const {
4126 const auto maybe = find_by_kid(key_id);
4127 if (maybe == end()) throw error::claim_not_present_exception();
4128 return *maybe;
4129 }
4130
4131 private:
4132 jwks_vector_t jwk_claims;
4133
4134 const_iterator find_by_kid(const typename json_traits::string_type& key_id) const noexcept {
4135 return std::find_if(cbegin(), cend(), [key_id](const jwks_t& jwk) {
4136 if (!jwk.has_key_id()) { return false; }
4137 return jwk.get_key_id() == key_id;
4138 });
4139 }
4140 };
4141
4147 template<typename Clock, typename json_traits>
4151
4157 template<typename Clock, typename json_traits>
4161
4170 date now() const { return date::clock::now(); }
4171 };
4172
4181 template<typename json_traits>
4183 return verifier<default_clock, json_traits>(c);
4184 }
4185
4189 template<typename json_traits>
4191 return builder<default_clock, json_traits>(c);
4192 }
4193
4208 template<typename json_traits, typename Decode>
4209 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token, Decode decode) {
4210 return decoded_jwt<json_traits>(token, decode);
4211 }
4212
4223 template<typename json_traits>
4224 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token) {
4225 return decoded_jwt<json_traits>(token);
4226 }
4233 template<typename json_traits>
4234 jwk<json_traits> parse_jwk(const typename json_traits::string_type& jwk_) {
4235 return jwk<json_traits>(jwk_);
4236 }
4247 template<typename json_traits>
4248 jwks<json_traits> parse_jwks(const typename json_traits::string_type& jwks_) {
4249 return jwks<json_traits>(jwks_);
4250 }
4251} // namespace jwt
4252
4253template<typename json_traits>
4254std::istream& operator>>(std::istream& is, jwt::basic_claim<json_traits>& c) {
4255 return c.operator>>(is);
4256}
4257
4258template<typename json_traits>
4259std::ostream& operator<<(std::ostream& os, const jwt::basic_claim<json_traits>& c) {
4260 return os << c.to_json();
4261}
4262
4263#ifndef JWT_DISABLE_PICOJSON
4264#include "traits/kazuho-picojson/defaults.h"
4265#endif
4266
4267#endif
a class to store a generic JSON value as claim
Definition jwt.h:2586
json_traits::number_type as_number() const
Definition jwt.h:2717
set_t as_set() const
Definition jwt.h:2690
json::type get_type() const
Definition jwt.h:2654
std::set< typename json_traits::string_type > set_t
Definition jwt.h:2612
std::istream & operator>>(std::istream &is)
Definition jwt.h:2641
json_traits::boolean_type as_boolean() const
Definition jwt.h:2710
date as_date() const
Get the contained JSON value as a date.
Definition jwt.h:2671
std::ostream & operator<<(std::ostream &os)
Definition jwt.h:2647
json_traits::integer_type as_integer() const
Definition jwt.h:2703
json_traits::value_type to_json() const
Definition jwt.h:2635
json_traits::array_type as_array() const
Definition jwt.h:2683
json_traits::string_type as_string() const
Definition jwt.h:2661
Definition jwt.h:3128
builder & set_audience(typename json_traits::string_type aud)
Definition jwt.h:3246
builder & set_payload_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition jwt.h:3178
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:3189
builder & set_expires_at(const date &d)
Definition jwt.h:3254
builder & set_expires_in(const std::chrono::duration< Rep, Period > &d)
Definition jwt.h:3261
builder & set_type(typename json_traits::string_type str)
Definition jwt.h:3197
JWT_CLAIM_EXPLICIT builder(Clock c)
Definition jwt.h:3140
json_traits::string_type sign(const Algo &algo, std::error_code &ec) const
Definition jwt.h:3364
builder & set_issued_at(const date &d)
Definition jwt.h:3275
json_traits::string_type sign(const Algo &algo) const
Definition jwt.h:3318
builder & set_payload_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition jwt.h:3168
builder & set_id(const typename json_traits::string_type &str)
Definition jwt.h:3286
builder & set_header_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition jwt.h:3147
builder & set_header_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition jwt.h:3158
json_traits::string_type sign(const Algo &algo, Encode encode) const
Definition jwt.h:3302
builder & set_audience(typename json_traits::array_type a)
Definition jwt.h:3238
json_traits::string_type sign(const Algo &algo, Encode encode, std::error_code &ec) const
Definition jwt.h:3339
builder & set_content_type(typename json_traits::string_type str)
Definition jwt.h:3205
builder & set_not_before(const date &d)
Definition jwt.h:3269
builder & set_subject(typename json_traits::string_type str)
Definition jwt.h:3230
builder & set_issued_now()
Definition jwt.h:3280
builder & set_key_id(typename json_traits::string_type str)
Set key id claim.
Definition jwt.h:3214
builder & set_issuer(typename json_traits::string_type str)
Definition jwt.h:3222
Definition jwt.h:2993
const json_traits::string_type & get_header() const noexcept
Definition jwt.h:3065
const json_traits::string_type & get_signature_base64() const noexcept
Definition jwt.h:3090
json_traits::string_type signature
Signature part decoded from base64.
Definition jwt.h:3006
json_traits::string_type header
Header part decoded from base64.
Definition jwt.h:2998
json_traits::string_type header_base64
Unmodified header part in base64.
Definition jwt.h:3000
json_traits::string_type token
Unmodified token, as passed to constructor.
Definition jwt.h:2996
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition jwt.h:3108
const json_traits::string_type & get_signature() const noexcept
Definition jwt.h:3075
JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type &token)
Parses a given token.
Definition jwt.h:3022
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition jwt.h:3118
decoded_jwt(const typename json_traits::string_type &token, Decode decode)
Parses a given token.
Definition jwt.h:3039
json_traits::object_type get_payload_json() const
Definition jwt.h:3095
json_traits::string_type signature_base64
Unmodified signature part in base64.
Definition jwt.h:3008
const json_traits::string_type & get_payload_base64() const noexcept
Definition jwt.h:3085
const json_traits::string_type & get_token() const noexcept
Definition jwt.h:3060
json_traits::object_type get_header_json() const
Definition jwt.h:3100
const json_traits::string_type & get_payload() const noexcept
Definition jwt.h:3070
const json_traits::string_type & get_header_base64() const noexcept
Definition jwt.h:3080
json_traits::string_type payload_base64
Unmodified payload part in base64.
Definition jwt.h:3004
json_traits::string_type payload
Payload part decoded from base64.
Definition jwt.h:3002
Definition jwt.h:2918
json_traits::string_type get_type() const
Definition jwt.h:2957
bool has_header_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:2976
bool has_algorithm() const noexcept
Definition jwt.h:2928
bool has_type() const noexcept
Definition jwt.h:2933
json_traits::string_type get_algorithm() const
Definition jwt.h:2950
bool has_content_type() const noexcept
Definition jwt.h:2938
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2984
json_traits::string_type get_key_id() const
Definition jwt.h:2971
json_traits::string_type get_content_type() const
Definition jwt.h:2964
bool has_key_id() const noexcept
Definition jwt.h:2943
Handle class for EVP_PKEY structures.
Definition jwt.h:425
constexpr evp_pkey_handle() noexcept=default
Creates a null key pointer.
constexpr evp_pkey_handle(EVP_PKEY *key) noexcept
Construct a new handle. The handle takes ownership of the key.
Definition jwt.h:449
JSON Web Key.
Definition jwt.h:3862
bool has_x5c() const noexcept
Definition jwt.h:4018
json_traits::string_type get_curve() const
Get curve claim.
Definition jwt.h:3925
bool has_x5t_sha256() const noexcept
Definition jwt.h:4030
json_traits::string_type get_algorithm() const
Definition jwt.h:3905
json_traits::array_type get_x5c() const
Definition jwt.h:3933
json_traits::object_type get_claims() const
Definition jwt.h:4059
json_traits::string_type get_x5t() const
Definition jwt.h:3949
json_traits::string_type get_x5c_key_value() const
Definition jwt.h:3965
json_traits::string_type get_x5t_sha256() const
Definition jwt.h:3957
json_traits::string_type get_key_id() const
Definition jwt.h:3913
bool has_algorithm() const noexcept
Definition jwt.h:3994
json_traits::string_type get_use() const
Definition jwt.h:3889
bool has_key_id() const noexcept
Definition jwt.h:4006
bool has_x5u() const noexcept
Definition jwt.h:4012
bool has_key_operations() const noexcept
Definition jwt.h:3988
bool empty() const noexcept
Definition jwt.h:4053
bool has_use() const noexcept
Definition jwt.h:3982
bool has_x5t() const noexcept
Definition jwt.h:4024
bool has_jwk_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:4036
basic_claim_t::set_t get_key_operations() const
Definition jwt.h:3897
bool has_curve() const noexcept
Definition jwt.h:4000
bool has_key_type() const noexcept
Definition jwt.h:3976
basic_claim_t get_jwk_claim(const typename json_traits::string_type &name) const
Definition jwt.h:4045
json_traits::string_type get_x5u() const
Definition jwt.h:3941
json_traits::string_type get_key_type() const
Definition jwt.h:3881
JWK Set.
Definition jwt.h:4073
jwks_t get_jwk(const typename json_traits::string_type &key_id) const
Definition jwt.h:4125
jwks()=default
std::vector< jwks_t > jwks_vector_t
Type specialization for the vector of JWK.
Definition jwt.h:4078
JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type &str)
Definition jwt.h:4093
bool has_jwk(const typename json_traits::string_type &key_id) const noexcept
Definition jwt.h:4116
Definition jwt.h:2800
basic_claim_t::set_t get_audience() const
Definition jwt.h:2862
json_traits::string_type get_id() const
Definition jwt.h:2895
bool has_issued_at() const noexcept
Definition jwt.h:2836
bool has_not_before() const noexcept
Definition jwt.h:2831
bool has_payload_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:2900
bool has_subject() const noexcept
Definition jwt.h:2816
date get_not_before() const
Definition jwt.h:2881
bool has_issuer() const noexcept
Definition jwt.h:2811
bool has_id() const noexcept
Definition jwt.h:2841
bool has_expires_at() const noexcept
Definition jwt.h:2826
date get_issued_at() const
Definition jwt.h:2888
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2908
bool has_audience() const noexcept
Definition jwt.h:2821
date get_expires_at() const
Definition jwt.h:2874
json_traits::string_type get_subject() const
Definition jwt.h:2855
json_traits::string_type get_issuer() const
Definition jwt.h:2848
Definition jwt.h:3599
verifier & expires_at_leeway(size_t leeway)
Definition jwt.h:3680
verifier & with_claim(const typename json_traits::string_type &name, verify_check_fn_t fn)
Definition jwt.h:3779
void verify(const decoded_jwt< json_traits > &jwt, std::error_code &ec) const
Definition jwt.h:3832
std::function< void(const verify_ops::verify_context< json_traits > &, std::error_code &ec)> verify_check_fn_t
Verification function data structure.
Definition jwt.h:3611
verifier & not_before_leeway(size_t leeway)
Definition jwt.h:3690
verifier & issued_at_leeway(size_t leeway)
Definition jwt.h:3700
verifier & with_subject(const typename json_traits::string_type &sub)
Definition jwt.h:3736
verifier & with_audience(const typename basic_claim_t::set_t &aud)
Definition jwt.h:3745
verifier & with_claim(const typename json_traits::string_type &name, basic_claim_t c)
Definition jwt.h:3794
verifier & with_audience(const typename json_traits::string_type &aud)
Definition jwt.h:3755
void verify(const decoded_jwt< json_traits > &jwt) const
Definition jwt.h:3822
verifier(Clock c)
Definition jwt.h:3641
verifier & leeway(size_t leeway)
Definition jwt.h:3670
verifier & with_issuer(const typename json_traits::string_type &iss)
Definition jwt.h:3726
verifier & allow_algorithm(Algorithm alg)
Add an algorithm available for checking.
Definition jwt.h:3812
verifier & with_type(const typename json_traits::string_type &type, std::locale locale=std::locale{})
Definition jwt.h:3716
verifier & with_id(const typename json_traits::string_type &id)
Definition jwt.h:3766
signature_verification_error
Errors related to verification of signatures.
Definition jwt.h:216
std::error_category & token_verification_error_category()
Error category for token verification errors.
Definition jwt.h:351
void throw_if_error(std::error_code ec)
Raises an exception if any JWT-CPP error codes are active.
Definition jwt.h:383
std::error_category & ecdsa_error_category()
Error category for ECDSA errors.
Definition jwt.h:179
std::error_category & signature_verification_error_category()
Error category for verification errors.
Definition jwt.h:230
std::error_category & rsa_error_category()
Error category for RSA errors.
Definition jwt.h:127
std::error_category & signature_generation_error_category()
Error category for signature generation errors.
Definition jwt.h:289
ecdsa_error
Errors related to processing of RSA signatures.
Definition jwt.h:159
rsa_error
Errors related to processing of RSA signatures.
Definition jwt.h:110
signature_generation_error
Errors related to signature generation errors.
Definition jwt.h:269
token_verification_error
Errors related to token verification errors.
Definition jwt.h:339
std::error_code make_error_code(rsa_error e)
Converts JWT-CPP errors into generic STL error_codes.
Definition jwt.h:155
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:542
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:828
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:714
std::string create_public_key_from_rsa_components(const std::string &modulus, const std::string &exponent, Decode decode, std::error_code &ec)
create public key from modulus and exponent. This is defined in RFC 7518 Section 6....
Definition jwt.h:927
std::unique_ptr< BIGNUM, decltype(&BN_free)> raw2bn(const std::string &raw, std::error_code &ec)
Definition jwt.h:857
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:907
int curve2nid(const std::string curve, std::error_code &ec)
Convert a curve name to an ID.
Definition jwt.h:1134
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:628
std::string bn2raw(const BIGNUM *bn)
Definition jwt.h:844
std::string create_public_key_from_ec_components(const std::string &curve, const std::string &x, const std::string &y, Decode decode, std::error_code &ec)
Definition jwt.h:1165
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:782
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:592
type
Categories for the various JSON types used in JWTs.
Definition jwt.h:2311
JSON Web Token.
Definition base.h:21
verifier< Clock, json_traits > verify(Clock c)
Definition jwt.h:4148
std::chrono::system_clock::time_point date
Definition jwt.h:86
builder< Clock, json_traits > create(Clock c)
Definition jwt.h:4158
verifier< default_clock, traits::boost_json > verify()
Definition defaults.h:23
jwk< json_traits > parse_jwk(const typename json_traits::string_type &jwk_)
Definition jwt.h:4234
jwks< json_traits > parse_jwks(const typename json_traits::string_type &jwks_)
Definition jwt.h:4248
decoded_jwt< json_traits > decode(const typename json_traits::string_type &token, Decode decode)
Decode a token. This can be used to to help access important feild like 'x5c' for verifying tokens....
Definition jwt.h:4209
verify_ops::verify_context< traits::boost_json > verify_context
Definition defaults.h:88
Base class for ECDSA family of algorithms.
Definition jwt.h:1563
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1653
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1616
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:1575
ecdsa(helper::evp_pkey_handle key_pair, const EVP_MD *(*md)(), std::string name, size_t siglen)
Definition jwt.h:1602
std::string name() const
Definition jwt.h:1692
Definition jwt.h:2215
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:2225
Definition jwt.h:2237
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:2247
Base class for EdDSA family of algorithms.
Definition jwt.h:1810
std::string name() const
Definition jwt.h:1924
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:1821
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1837
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1885
Definition jwt.h:2142
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:2152
Definition jwt.h:2193
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:2202
Definition jwt.h:2159
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:2169
Definition jwt.h:2176
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:2186
Base class for HMAC family of algorithms.
Definition jwt.h:1382
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1399
std::string name() const
Definition jwt.h:1439
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1420
hmacsha(std::string key, const EVP_MD *(*md)(), std::string name)
Definition jwt.h:1390
Definition jwt.h:2064
hs256(std::string key)
Definition jwt.h:2069
Definition jwt.h:2074
hs384(std::string key)
Definition jwt.h:2079
Definition jwt.h:2084
hs512(std::string key)
Definition jwt.h:2089
"none" algorithm.
Definition jwt.h:1357
void verify(const std::string &, const std::string &signature, std::error_code &ec) const
Check if the given signature is empty.
Definition jwt.h:1372
std::string name() const
Get algorithm name.
Definition jwt.h:1377
std::string sign(const std::string &, std::error_code &ec) const
Return an empty string.
Definition jwt.h:1361
Definition jwt.h:2256
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:2264
Definition jwt.h:2271
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:2279
Definition jwt.h:2286
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:2294
Base class for PSS-RSA family of algorithms.
Definition jwt.h:1936
std::string name() const
Definition jwt.h:2050
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:1946
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:2011
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1963
Definition jwt.h:2096
rs256(const std::string &public_key, const std::string &private_key="", const std::string &public_key_password="", const std::string &private_key_password="")
Construct new instance of algorithm.
Definition jwt.h:2105
Definition jwt.h:2112
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:2120
Definition jwt.h:2127
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:2135
Base class for RSA family of algorithms.
Definition jwt.h:1452
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1524
rsa(helper::evp_pkey_handle key_pair, const EVP_MD *(*md)(), std::string name)
Definition jwt.h:1480
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1490
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:1463
std::string name() const
Definition jwt.h:1550
Definition jwt.h:4165
date now() const
Definition jwt.h:4170
Definition jwt.h:101
Definition jwt.h:98
Definition jwt.h:3451
Definition jwt.h:3380
date current_time
Current time, retrieved from the verifiers clock and cached for performance and consistency.
Definition jwt.h:3384
basic_claim< json_traits > get_claim(bool in_header, json::type t, std::error_code &ec) const
Definition jwt.h:3421
size_t default_leeway
The configured default leeway for this verification.
Definition jwt.h:3388
basic_claim< json_traits > get_claim(bool in_header, std::error_code &ec) const
Helper method to get a claim from the jwt in this context.
Definition jwt.h:3399
basic_claim< json_traits > get_claim(json::type t, std::error_code &ec) const
Helper method to get a payload claim of a specific type from the jwt.
Definition jwt.h:3442
basic_claim< json_traits > get_claim(std::error_code &ec) const
Helper method to get a payload claim from the jwt.
Definition jwt.h:3435
json_traits::string_type claim_key
The claim key to apply this comparison on.
Definition jwt.h:3391
const decoded_jwt< json_traits > & jwt
The jwt passed to the verifier.
Definition jwt.h:3386