JWT-CPP v0.7.0
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 };
177 inline std::error_category& ecdsa_error_category() {
178 class ecdsa_error_cat : public std::error_category {
179 public:
180 const char* name() const noexcept override { return "ecdsa_error"; };
181 std::string message(int ev) const override {
182 switch (static_cast<ecdsa_error>(ev)) {
183 case ecdsa_error::ok: return "no error";
184 case ecdsa_error::load_key_bio_write: return "failed to load key: bio write failed";
185 case ecdsa_error::load_key_bio_read: return "failed to load key: bio read failed";
186 case ecdsa_error::create_mem_bio_failed: return "failed to create memory bio";
187 case ecdsa_error::no_key_provided:
188 return "at least one of public or private key need to be present";
189 case ecdsa_error::invalid_key_size: return "invalid key size";
190 case ecdsa_error::invalid_key: return "invalid key";
191 case ecdsa_error::create_context_failed: return "failed to create context";
192 case ecdsa_error::cert_load_failed: return "error loading cert into memory";
193 case ecdsa_error::get_key_failed: return "error getting key from certificate";
194 case ecdsa_error::write_key_failed: return "error writing key data in PEM format";
195 case ecdsa_error::write_cert_failed: return "error writing cert data in PEM format";
196 case ecdsa_error::convert_to_pem_failed: return "failed to convert key to pem";
197 default: return "unknown ECDSA error";
198 }
199 }
200 };
201 static ecdsa_error_cat cat;
202 return cat;
203 }
207 inline std::error_code make_error_code(ecdsa_error e) { return {static_cast<int>(e), ecdsa_error_category()}; }
208
213 ok = 0,
214 invalid_signature = 10,
215 create_context_failed,
216 verifyinit_failed,
217 verifyupdate_failed,
218 verifyfinal_failed,
219 get_key_failed,
220 set_rsa_pss_saltlen_failed,
221 signature_encoding_failed
222 };
226 inline std::error_category& signature_verification_error_category() {
227 class verification_error_cat : public std::error_category {
228 public:
229 const char* name() const noexcept override { return "signature_verification_error"; };
230 std::string message(int ev) const override {
231 switch (static_cast<signature_verification_error>(ev)) {
232 case signature_verification_error::ok: return "no error";
233 case signature_verification_error::invalid_signature: return "invalid signature";
234 case signature_verification_error::create_context_failed:
235 return "failed to verify signature: could not create context";
236 case signature_verification_error::verifyinit_failed:
237 return "failed to verify signature: VerifyInit failed";
238 case signature_verification_error::verifyupdate_failed:
239 return "failed to verify signature: VerifyUpdate failed";
240 case signature_verification_error::verifyfinal_failed:
241 return "failed to verify signature: VerifyFinal failed";
242 case signature_verification_error::get_key_failed:
243 return "failed to verify signature: Could not get key";
244 case signature_verification_error::set_rsa_pss_saltlen_failed:
245 return "failed to verify signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
246 case signature_verification_error::signature_encoding_failed:
247 return "failed to verify signature: i2d_ECDSA_SIG failed";
248 default: return "unknown signature verification error";
249 }
250 }
251 };
252 static verification_error_cat cat;
253 return cat;
254 }
259 return {static_cast<int>(e), signature_verification_error_category()};
260 }
261
266 ok = 0,
267 hmac_failed = 10,
268 create_context_failed,
269 signinit_failed,
270 signupdate_failed,
271 signfinal_failed,
272 ecdsa_do_sign_failed,
273 digestinit_failed,
274 digestupdate_failed,
275 digestfinal_failed,
276 rsa_padding_failed,
277 rsa_private_encrypt_failed,
278 get_key_failed,
279 set_rsa_pss_saltlen_failed,
280 signature_decoding_failed
281 };
285 inline std::error_category& signature_generation_error_category() {
286 class signature_generation_error_cat : public std::error_category {
287 public:
288 const char* name() const noexcept override { return "signature_generation_error"; };
289 std::string message(int ev) const override {
290 switch (static_cast<signature_generation_error>(ev)) {
291 case signature_generation_error::ok: return "no error";
292 case signature_generation_error::hmac_failed: return "hmac failed";
293 case signature_generation_error::create_context_failed:
294 return "failed to create signature: could not create context";
295 case signature_generation_error::signinit_failed:
296 return "failed to create signature: SignInit failed";
297 case signature_generation_error::signupdate_failed:
298 return "failed to create signature: SignUpdate failed";
299 case signature_generation_error::signfinal_failed:
300 return "failed to create signature: SignFinal failed";
301 case signature_generation_error::ecdsa_do_sign_failed: return "failed to generate ecdsa signature";
302 case signature_generation_error::digestinit_failed:
303 return "failed to create signature: DigestInit failed";
304 case signature_generation_error::digestupdate_failed:
305 return "failed to create signature: DigestUpdate failed";
306 case signature_generation_error::digestfinal_failed:
307 return "failed to create signature: DigestFinal failed";
308 case signature_generation_error::rsa_padding_failed:
309 return "failed to create signature: EVP_PKEY_CTX_set_rsa_padding failed";
310 case signature_generation_error::rsa_private_encrypt_failed:
311 return "failed to create signature: RSA_private_encrypt failed";
312 case signature_generation_error::get_key_failed:
313 return "failed to generate signature: Could not get key";
314 case signature_generation_error::set_rsa_pss_saltlen_failed:
315 return "failed to create signature: EVP_PKEY_CTX_set_rsa_pss_saltlen failed";
316 case signature_generation_error::signature_decoding_failed:
317 return "failed to create signature: d2i_ECDSA_SIG failed";
318 default: return "unknown signature generation error";
319 }
320 }
321 };
322 static signature_generation_error_cat cat = {};
323 return cat;
324 }
328 inline std::error_code make_error_code(signature_generation_error e) {
329 return {static_cast<int>(e), signature_generation_error_category()};
330 }
331
336 ok = 0,
337 wrong_algorithm = 10,
338 missing_claim,
339 claim_type_missmatch,
340 claim_value_missmatch,
341 token_expired,
342 audience_missmatch
343 };
347 inline std::error_category& token_verification_error_category() {
348 class token_verification_error_cat : public std::error_category {
349 public:
350 const char* name() const noexcept override { return "token_verification_error"; };
351 std::string message(int ev) const override {
352 switch (static_cast<token_verification_error>(ev)) {
353 case token_verification_error::ok: return "no error";
354 case token_verification_error::wrong_algorithm: return "wrong algorithm";
355 case token_verification_error::missing_claim: return "decoded JWT is missing required claim(s)";
356 case token_verification_error::claim_type_missmatch:
357 return "claim type does not match expected type";
358 case token_verification_error::claim_value_missmatch:
359 return "claim value does not match expected value";
360 case token_verification_error::token_expired: return "token expired";
361 case token_verification_error::audience_missmatch:
362 return "token doesn't contain the required audience";
363 default: return "unknown token verification error";
364 }
365 }
366 };
367 static token_verification_error_cat cat = {};
368 return cat;
369 }
373 inline std::error_code make_error_code(token_verification_error e) {
374 return {static_cast<int>(e), token_verification_error_category()};
375 }
379 inline void throw_if_error(std::error_code ec) {
380 if (ec) {
381 if (ec.category() == rsa_error_category()) throw rsa_exception(ec);
382 if (ec.category() == ecdsa_error_category()) throw ecdsa_exception(ec);
383 if (ec.category() == signature_verification_error_category())
386 if (ec.category() == token_verification_error_category()) throw token_verification_exception(ec);
387 }
388 }
389 } // namespace error
390} // namespace jwt
391
392namespace std {
393 template<>
394 struct is_error_code_enum<jwt::error::rsa_error> : true_type {};
395 template<>
396 struct is_error_code_enum<jwt::error::ecdsa_error> : true_type {};
397 template<>
398 struct is_error_code_enum<jwt::error::signature_verification_error> : true_type {};
399 template<>
400 struct is_error_code_enum<jwt::error::signature_generation_error> : true_type {};
401 template<>
402 struct is_error_code_enum<jwt::error::token_verification_error> : true_type {};
403} // namespace std
404
405namespace jwt {
413 namespace helper {
422 public:
426 constexpr evp_pkey_handle() noexcept = default;
427#ifdef JWT_OPENSSL_1_0_0
432 explicit evp_pkey_handle(EVP_PKEY* key) { m_key = std::shared_ptr<EVP_PKEY>(key, EVP_PKEY_free); }
433
434 EVP_PKEY* get() const noexcept { return m_key.get(); }
435 bool operator!() const noexcept { return m_key == nullptr; }
436 explicit operator bool() const noexcept { return m_key != nullptr; }
437
438 private:
439 std::shared_ptr<EVP_PKEY> m_key{nullptr};
440#else
445 explicit constexpr evp_pkey_handle(EVP_PKEY* key) noexcept : m_key{key} {}
446 evp_pkey_handle(const evp_pkey_handle& other) : m_key{other.m_key} {
447 if (m_key != nullptr && EVP_PKEY_up_ref(m_key) != 1) throw std::runtime_error("EVP_PKEY_up_ref failed");
448 }
449// C++11 requires the body of a constexpr constructor to be empty
450#if __cplusplus >= 201402L
451 constexpr
452#endif
453 evp_pkey_handle(evp_pkey_handle&& other) noexcept
454 : m_key{other.m_key} {
455 other.m_key = nullptr;
456 }
457 evp_pkey_handle& operator=(const evp_pkey_handle& other) {
458 if (&other == this) return *this;
459 decrement_ref_count(m_key);
460 m_key = other.m_key;
461 increment_ref_count(m_key);
462 return *this;
463 }
464 evp_pkey_handle& operator=(evp_pkey_handle&& other) noexcept {
465 if (&other == this) return *this;
466 decrement_ref_count(m_key);
467 m_key = other.m_key;
468 other.m_key = nullptr;
469 return *this;
470 }
471 evp_pkey_handle& operator=(EVP_PKEY* key) {
472 decrement_ref_count(m_key);
473 m_key = key;
474 increment_ref_count(m_key);
475 return *this;
476 }
477 ~evp_pkey_handle() noexcept { decrement_ref_count(m_key); }
478
479 EVP_PKEY* get() const noexcept { return m_key; }
480 bool operator!() const noexcept { return m_key == nullptr; }
481 explicit operator bool() const noexcept { return m_key != nullptr; }
482
483 private:
484 EVP_PKEY* m_key{nullptr};
485
486 static void increment_ref_count(EVP_PKEY* key) {
487 if (key != nullptr && EVP_PKEY_up_ref(key) != 1) throw std::runtime_error("EVP_PKEY_up_ref failed");
488 }
489 static void decrement_ref_count(EVP_PKEY* key) noexcept {
490 if (key != nullptr) EVP_PKEY_free(key);
491 }
492#endif
493 };
494
495 inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio() {
496 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(BIO_new(BIO_s_mem()), BIO_free_all);
497 }
498
499 inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio(const std::string& data) {
500 return std::unique_ptr<BIO, decltype(&BIO_free_all)>(
501#if OPENSSL_VERSION_NUMBER <= 0x10100003L
502 BIO_new_mem_buf(const_cast<char*>(data.data()), static_cast<int>(data.size())), BIO_free_all
503#else
504 BIO_new_mem_buf(data.data(), static_cast<int>(data.size())), BIO_free_all
505#endif
506 );
507 }
508
509 template<typename error_category = error::rsa_error>
510 std::string write_bio_to_string(std::unique_ptr<BIO, decltype(&BIO_free_all)>& bio_out, std::error_code& ec) {
511 char* ptr = nullptr;
512 auto len = BIO_get_mem_data(bio_out.get(), &ptr);
513 if (len <= 0 || ptr == nullptr) {
514 ec = error_category::convert_to_pem_failed;
515 return {};
516 }
517 return {ptr, static_cast<size_t>(len)};
518 }
519
520 inline std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> make_evp_md_ctx() {
521 return
522#ifdef JWT_OPENSSL_1_0_0
523 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), &EVP_MD_CTX_destroy);
524#else
525 std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), &EVP_MD_CTX_free);
526#endif
527 }
528
537 template<typename error_category = error::rsa_error>
538 std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw, std::error_code& ec) {
539 ec.clear();
540 auto certbio = make_mem_buf_bio(certstr);
541 auto keybio = make_mem_buf_bio();
542 if (!certbio || !keybio) {
543 ec = error_category::create_mem_bio_failed;
544 return {};
545 }
546
547 std::unique_ptr<X509, decltype(&X509_free)> cert(
548 PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())), X509_free);
549 if (!cert) {
550 ec = error_category::cert_load_failed;
551 return {};
552 }
553 std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()), EVP_PKEY_free);
554 if (!key) {
555 ec = error_category::get_key_failed;
556 return {};
557 }
558 if (PEM_write_bio_PUBKEY(keybio.get(), key.get()) == 0) {
559 ec = error_category::write_key_failed;
560 return {};
561 }
562
563 return write_bio_to_string<error_category>(keybio, ec);
564 }
565
574 template<typename error_category = error::rsa_error>
575 std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw = "") {
576 std::error_code ec;
577 auto res = extract_pubkey_from_cert<error_category>(certstr, pw, ec);
579 return res;
580 }
581
588 inline std::string convert_der_to_pem(const std::string& cert_der_str, std::error_code& ec) {
589 ec.clear();
590
591 auto c_str = reinterpret_cast<const unsigned char*>(cert_der_str.c_str());
592
593 std::unique_ptr<X509, decltype(&X509_free)> cert(
594 d2i_X509(NULL, &c_str, static_cast<int>(cert_der_str.size())), X509_free);
595 auto certbio = make_mem_buf_bio();
596 if (!cert || !certbio) {
597 ec = error::rsa_error::create_mem_bio_failed;
598 return {};
599 }
600
601 if (!PEM_write_bio_X509(certbio.get(), cert.get())) {
602 ec = error::rsa_error::write_cert_failed;
603 return {};
604 }
605
606 return write_bio_to_string(certbio, ec);
607 }
608
623 template<typename Decode>
624 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode,
625 std::error_code& ec) {
626 ec.clear();
627 const auto decoded_str = decode(cert_base64_der_str);
628 return convert_der_to_pem(decoded_str, ec);
629 }
630
645 template<typename Decode>
646 std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, Decode decode) {
647 std::error_code ec;
648 auto res = convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
650 return res;
651 }
652
659 inline std::string convert_der_to_pem(const std::string& cert_der_str) {
660 std::error_code ec;
661 auto res = convert_der_to_pem(cert_der_str, ec);
663 return res;
664 }
665
666#ifndef JWT_DISABLE_BASE64
676 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str, std::error_code& ec) {
677 auto decode = [](const std::string& token) {
678 return base::decode<alphabet::base64>(base::pad<alphabet::base64>(token));
679 };
680 return convert_base64_der_to_pem(cert_base64_der_str, std::move(decode), ec);
681 }
682
692 inline std::string convert_base64_der_to_pem(const std::string& cert_base64_der_str) {
693 std::error_code ec;
694 auto res = convert_base64_der_to_pem(cert_base64_der_str, ec);
696 return res;
697 }
698#endif
709 template<typename error_category = error::rsa_error>
710 evp_pkey_handle load_public_key_from_string(const std::string& key, const std::string& password,
711 std::error_code& ec) {
712 ec.clear();
713 auto pubkey_bio = make_mem_buf_bio();
714 if (!pubkey_bio) {
715 ec = error_category::create_mem_bio_failed;
716 return {};
717 }
718 if (key.substr(0, 27) == "-----BEGIN CERTIFICATE-----") {
719 auto epkey = helper::extract_pubkey_from_cert<error_category>(key, password, ec);
720 if (ec) return {};
721 const int len = static_cast<int>(epkey.size());
722 if (BIO_write(pubkey_bio.get(), epkey.data(), len) != len) {
723 ec = error_category::load_key_bio_write;
724 return {};
725 }
726 } else {
727 const int len = static_cast<int>(key.size());
728 if (BIO_write(pubkey_bio.get(), key.data(), len) != len) {
729 ec = error_category::load_key_bio_write;
730 return {};
731 }
732 }
733
734 evp_pkey_handle pkey(PEM_read_bio_PUBKEY(
735 pubkey_bio.get(), nullptr, nullptr,
736 (void*)password.data())); // NOLINT(google-readability-casting) requires `const_cast`
737 if (!pkey) ec = error_category::load_key_bio_read;
738 return pkey;
739 }
740
751 template<typename error_category = error::rsa_error>
752 inline evp_pkey_handle load_public_key_from_string(const std::string& key, const std::string& password = "") {
753 std::error_code ec;
754 auto res = load_public_key_from_string<error_category>(key, password, ec);
756 return res;
757 }
758
767 template<typename error_category = error::rsa_error>
768 inline evp_pkey_handle load_private_key_from_string(const std::string& key, const std::string& password,
769 std::error_code& ec) {
770 ec.clear();
771 auto private_key_bio = make_mem_buf_bio();
772 if (!private_key_bio) {
773 ec = error_category::create_mem_bio_failed;
774 return {};
775 }
776 const int len = static_cast<int>(key.size());
777 if (BIO_write(private_key_bio.get(), key.data(), len) != len) {
778 ec = error_category::load_key_bio_write;
779 return {};
780 }
781 evp_pkey_handle pkey(
782 PEM_read_bio_PrivateKey(private_key_bio.get(), nullptr, nullptr, const_cast<char*>(password.c_str())));
783 if (!pkey) ec = error_category::load_key_bio_read;
784 return pkey;
785 }
786
795 template<typename error_category = error::rsa_error>
796 inline evp_pkey_handle load_private_key_from_string(const std::string& key, const std::string& password = "") {
797 std::error_code ec;
798 auto res = load_private_key_from_string<error_category>(key, password, ec);
800 return res;
801 }
802
814 inline evp_pkey_handle load_public_ec_key_from_string(const std::string& key, const std::string& password,
815 std::error_code& ec) {
816 return load_public_key_from_string<error::ecdsa_error>(key, password, ec);
817 }
818
824 inline
825#ifdef JWT_OPENSSL_1_0_0
826 std::string
827 bn2raw(BIGNUM* bn)
828#else
829 std::string
830 bn2raw(const BIGNUM* bn)
831#endif
832 {
833 std::string res(BN_num_bytes(bn), '\0');
834 BN_bn2bin(bn, (unsigned char*)res.data()); // NOLINT(google-readability-casting) requires `const_cast`
835 return res;
836 }
843 inline std::unique_ptr<BIGNUM, decltype(&BN_free)> raw2bn(const std::string& raw, std::error_code& ec) {
844 auto bn =
845 BN_bin2bn(reinterpret_cast<const unsigned char*>(raw.data()), static_cast<int>(raw.size()), nullptr);
846 // https://www.openssl.org/docs/man1.1.1/man3/BN_bin2bn.html#RETURN-VALUES
847 if (!bn) {
848 ec = error::rsa_error::set_rsa_failed;
849 return {nullptr, BN_free};
850 }
851 return {bn, BN_free};
852 }
858 inline std::unique_ptr<BIGNUM, decltype(&BN_free)> raw2bn(const std::string& raw) {
859 std::error_code ec;
860 auto res = raw2bn(raw, ec);
862 return res;
863 }
864
876 inline evp_pkey_handle load_public_ec_key_from_string(const std::string& key,
877 const std::string& password = "") {
878 std::error_code ec;
879 auto res = load_public_key_from_string<error::ecdsa_error>(key, password, ec);
881 return res;
882 }
883
893 inline evp_pkey_handle load_private_ec_key_from_string(const std::string& key, const std::string& password,
894 std::error_code& ec) {
895 return load_private_key_from_string<error::ecdsa_error>(key, password, ec);
896 }
897
912 template<typename Decode>
913 std::string create_public_key_from_rsa_components(const std::string& modulus, const std::string& exponent,
914 Decode decode, std::error_code& ec) {
915 ec.clear();
916 auto decoded_modulus = decode(modulus);
917 auto decoded_exponent = decode(exponent);
918
919 auto n = helper::raw2bn(decoded_modulus, ec);
920 if (ec) return {};
921 auto e = helper::raw2bn(decoded_exponent, ec);
922 if (ec) return {};
923
924#if defined(JWT_OPENSSL_3_0)
925 // OpenSSL deprecated mutable keys and there is a new way for making them
926 // https://mta.openssl.org/pipermail/openssl-users/2021-July/013994.html
927 // https://www.openssl.org/docs/man3.1/man3/OSSL_PARAM_BLD_new.html#Example-2
928 std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)> param_bld(OSSL_PARAM_BLD_new(),
929 OSSL_PARAM_BLD_free);
930 if (!param_bld) {
931 ec = error::rsa_error::create_context_failed;
932 return {};
933 }
934
935 if (OSSL_PARAM_BLD_push_BN(param_bld.get(), "n", n.get()) != 1 ||
936 OSSL_PARAM_BLD_push_BN(param_bld.get(), "e", e.get()) != 1) {
937 ec = error::rsa_error::set_rsa_failed;
938 return {};
939 }
940
941 std::unique_ptr<OSSL_PARAM, decltype(&OSSL_PARAM_free)> params(OSSL_PARAM_BLD_to_param(param_bld.get()),
942 OSSL_PARAM_free);
943 if (!params) {
944 ec = error::rsa_error::set_rsa_failed;
945 return {};
946 }
947
948 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
949 EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr), EVP_PKEY_CTX_free);
950 if (!ctx) {
951 ec = error::rsa_error::create_context_failed;
952 return {};
953 }
954
955 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html#EXAMPLES
956 // Error codes based on https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_fromdata_init.html#RETURN-VALUES
957 EVP_PKEY* pkey = NULL;
958 if (EVP_PKEY_fromdata_init(ctx.get()) <= 0 ||
959 EVP_PKEY_fromdata(ctx.get(), &pkey, EVP_PKEY_KEYPAIR, params.get()) <= 0) {
960 // It's unclear if this can fail after allocating but free it anyways
961 // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_fromdata.html
962 EVP_PKEY_free(pkey);
963
964 ec = error::rsa_error::cert_load_failed;
965 return {};
966 }
967
968 // Transfer ownership so we get ref counter and cleanup
969 evp_pkey_handle rsa(pkey);
970
971#else
972 std::unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
973
974#if defined(JWT_OPENSSL_1_1_1) || defined(JWT_OPENSSL_1_1_0)
975 // After this RSA_free will also free the n and e big numbers
976 // See https://github.com/Thalhammer/jwt-cpp/pull/298#discussion_r1282619186
977 if (RSA_set0_key(rsa.get(), n.get(), e.get(), nullptr) == 1) {
978 // This can only fail we passed in NULL for `n` or `e`
979 // https://github.com/openssl/openssl/blob/d6e4056805f54bb1a0ef41fa3a6a35b70c94edba/crypto/rsa/rsa_lib.c#L396
980 // So to make sure there is no memory leak, we hold the references
981 n.release();
982 e.release();
983 } else {
984 ec = error::rsa_error::set_rsa_failed;
985 return {};
986 }
987#elif defined(JWT_OPENSSL_1_0_0)
988 rsa->e = e.release();
989 rsa->n = n.release();
990 rsa->d = nullptr;
991#endif
992#endif
993
994 auto pub_key_bio = make_mem_buf_bio();
995 if (!pub_key_bio) {
996 ec = error::rsa_error::create_mem_bio_failed;
997 return {};
998 }
999
1000 auto write_pem_to_bio =
1001#if defined(JWT_OPENSSL_3_0)
1002 // https://www.openssl.org/docs/man3.1/man3/PEM_write_bio_RSA_PUBKEY.html
1003 &PEM_write_bio_PUBKEY;
1004#else
1005 &PEM_write_bio_RSA_PUBKEY;
1006#endif
1007 if (write_pem_to_bio(pub_key_bio.get(), rsa.get()) != 1) {
1008 ec = error::rsa_error::load_key_bio_write;
1009 return {};
1010 }
1011
1012 return write_bio_to_string<error::rsa_error>(pub_key_bio, ec);
1013 }
1014
1028 template<typename Decode>
1029 std::string create_public_key_from_rsa_components(const std::string& modulus, const std::string& exponent,
1030 Decode decode) {
1031 std::error_code ec;
1032 auto res = create_public_key_from_rsa_components(modulus, exponent, decode, ec);
1034 return res;
1035 }
1036
1037#ifndef JWT_DISABLE_BASE64
1048 inline std::string create_public_key_from_rsa_components(const std::string& modulus,
1049 const std::string& exponent, std::error_code& ec) {
1050 auto decode = [](const std::string& token) {
1051 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(token));
1052 };
1053 return create_public_key_from_rsa_components(modulus, exponent, std::move(decode), ec);
1054 }
1064 inline std::string create_public_key_from_rsa_components(const std::string& modulus,
1065 const std::string& exponent) {
1066 std::error_code ec;
1067 auto res = create_public_key_from_rsa_components(modulus, exponent, ec);
1069 return res;
1070 }
1071#endif
1082 const std::string& password = "") {
1083 std::error_code ec;
1084 auto res = load_private_key_from_string<error::ecdsa_error>(key, password, ec);
1086 return res;
1087 }
1088 } // namespace helper
1089
1099 namespace algorithm {
1107 struct none {
1111 std::string sign(const std::string& /*unused*/, std::error_code& ec) const {
1112 ec.clear();
1113 return {};
1114 }
1122 void verify(const std::string& /*unused*/, const std::string& signature, std::error_code& ec) const {
1123 ec.clear();
1124 if (!signature.empty()) { ec = error::signature_verification_error::invalid_signature; }
1125 }
1127 std::string name() const { return "none"; }
1128 };
1132 struct hmacsha {
1140 hmacsha(std::string key, const EVP_MD* (*md)(), std::string name)
1141 : secret(std::move(key)), md(md), alg_name(std::move(name)) {}
1149 std::string sign(const std::string& data, std::error_code& ec) const {
1150 ec.clear();
1151 std::string res(static_cast<size_t>(EVP_MAX_MD_SIZE), '\0');
1152 auto len = static_cast<unsigned int>(res.size());
1153 if (HMAC(md(), secret.data(), static_cast<int>(secret.size()),
1154 reinterpret_cast<const unsigned char*>(data.data()), static_cast<int>(data.size()),
1155 (unsigned char*)res.data(), // NOLINT(google-readability-casting) requires `const_cast`
1156 &len) == nullptr) {
1157 ec = error::signature_generation_error::hmac_failed;
1158 return {};
1159 }
1160 res.resize(len);
1161 return res;
1162 }
1170 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1171 ec.clear();
1172 auto res = sign(data, ec);
1173 if (ec) return;
1174
1175 bool matched = true;
1176 for (size_t i = 0; i < std::min<size_t>(res.size(), signature.size()); i++)
1177 if (res[i] != signature[i]) matched = false;
1178 if (res.size() != signature.size()) matched = false;
1179 if (!matched) {
1180 ec = error::signature_verification_error::invalid_signature;
1181 return;
1182 }
1183 }
1189 std::string name() const { return alg_name; }
1190
1191 private:
1193 const std::string secret;
1195 const EVP_MD* (*md)();
1197 const std::string alg_name;
1198 };
1202 struct rsa {
1213 rsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1214 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name)
1215 : md(md), alg_name(std::move(name)) {
1216 if (!private_key.empty()) {
1217 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1218 } else if (!public_key.empty()) {
1219 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1220 } else
1221 throw error::rsa_exception(error::rsa_error::no_key_provided);
1222 }
1229 std::string sign(const std::string& data, std::error_code& ec) const {
1230 ec.clear();
1231 auto ctx = helper::make_evp_md_ctx();
1232 if (!ctx) {
1233 ec = error::signature_generation_error::create_context_failed;
1234 return {};
1235 }
1236 if (!EVP_SignInit(ctx.get(), md())) {
1237 ec = error::signature_generation_error::signinit_failed;
1238 return {};
1239 }
1240
1241 std::string res(EVP_PKEY_size(pkey.get()), '\0');
1242 unsigned int len = 0;
1243
1244 if (!EVP_SignUpdate(ctx.get(), data.data(), data.size())) {
1245 ec = error::signature_generation_error::signupdate_failed;
1246 return {};
1247 }
1248 if (EVP_SignFinal(ctx.get(), (unsigned char*)res.data(), &len, pkey.get()) == 0) {
1249 ec = error::signature_generation_error::signfinal_failed;
1250 return {};
1251 }
1252
1253 res.resize(len);
1254 return res;
1255 }
1263 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1264 ec.clear();
1265 auto ctx = helper::make_evp_md_ctx();
1266 if (!ctx) {
1267 ec = error::signature_verification_error::create_context_failed;
1268 return;
1269 }
1270 if (!EVP_VerifyInit(ctx.get(), md())) {
1271 ec = error::signature_verification_error::verifyinit_failed;
1272 return;
1273 }
1274 if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size())) {
1275 ec = error::signature_verification_error::verifyupdate_failed;
1276 return;
1277 }
1278 auto res = EVP_VerifyFinal(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1279 static_cast<unsigned int>(signature.size()), pkey.get());
1280 if (res != 1) {
1281 ec = error::signature_verification_error::verifyfinal_failed;
1282 return;
1283 }
1284 }
1289 std::string name() const { return alg_name; }
1290
1291 private:
1295 const EVP_MD* (*md)();
1297 const std::string alg_name;
1298 };
1302 struct ecdsa {
1314 ecdsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1315 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name, size_t siglen)
1316 : md(md), alg_name(std::move(name)), signature_length(siglen) {
1317 if (!private_key.empty()) {
1318 pkey = helper::load_private_ec_key_from_string(private_key, private_key_password);
1319 check_private_key(pkey.get());
1320 } else if (!public_key.empty()) {
1321 pkey = helper::load_public_ec_key_from_string(public_key, public_key_password);
1322 check_public_key(pkey.get());
1323 } else {
1324 throw error::ecdsa_exception(error::ecdsa_error::no_key_provided);
1325 }
1326 if (!pkey) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1327
1328 size_t keysize = EVP_PKEY_bits(pkey.get());
1329 if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521))
1330 throw error::ecdsa_exception(error::ecdsa_error::invalid_key_size);
1331 }
1332
1339 std::string sign(const std::string& data, std::error_code& ec) const {
1340 ec.clear();
1341 auto ctx = helper::make_evp_md_ctx();
1342 if (!ctx) {
1343 ec = error::signature_generation_error::create_context_failed;
1344 return {};
1345 }
1346 if (!EVP_DigestSignInit(ctx.get(), nullptr, md(), nullptr, pkey.get())) {
1347 ec = error::signature_generation_error::signinit_failed;
1348 return {};
1349 }
1350 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size())) {
1351 ec = error::signature_generation_error::digestupdate_failed;
1352 return {};
1353 }
1354
1355 size_t len = 0;
1356 if (!EVP_DigestSignFinal(ctx.get(), nullptr, &len)) {
1357 ec = error::signature_generation_error::signfinal_failed;
1358 return {};
1359 }
1360 std::string res(len, '\0');
1361 if (!EVP_DigestSignFinal(ctx.get(), (unsigned char*)res.data(), &len)) {
1362 ec = error::signature_generation_error::signfinal_failed;
1363 return {};
1364 }
1365
1366 res.resize(len);
1367 return der_to_p1363_signature(res, ec);
1368 }
1369
1376 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1377 ec.clear();
1378 std::string der_signature = p1363_to_der_signature(signature, ec);
1379 if (ec) { return; }
1380
1381 auto ctx = helper::make_evp_md_ctx();
1382 if (!ctx) {
1383 ec = error::signature_verification_error::create_context_failed;
1384 return;
1385 }
1386 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, md(), nullptr, pkey.get())) {
1387 ec = error::signature_verification_error::verifyinit_failed;
1388 return;
1389 }
1390 if (!EVP_DigestUpdate(ctx.get(), data.data(), data.size())) {
1391 ec = error::signature_verification_error::verifyupdate_failed;
1392 return;
1393 }
1394
1395#if OPENSSL_VERSION_NUMBER < 0x10002000L
1396 unsigned char* der_sig_data = reinterpret_cast<unsigned char*>(const_cast<char*>(der_signature.data()));
1397#else
1398 const unsigned char* der_sig_data = reinterpret_cast<const unsigned char*>(der_signature.data());
1399#endif
1400 auto res =
1401 EVP_DigestVerifyFinal(ctx.get(), der_sig_data, static_cast<unsigned int>(der_signature.length()));
1402 if (res == 0) {
1403 ec = error::signature_verification_error::invalid_signature;
1404 return;
1405 }
1406 if (res == -1) {
1407 ec = error::signature_verification_error::verifyfinal_failed;
1408 return;
1409 }
1410 }
1415 std::string name() const { return alg_name; }
1416
1417 private:
1418 static void check_public_key(EVP_PKEY* pkey) {
1419#ifdef JWT_OPENSSL_3_0
1420 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
1421 EVP_PKEY_CTX_new_from_pkey(nullptr, pkey, nullptr), EVP_PKEY_CTX_free);
1422 if (!ctx) { throw error::ecdsa_exception(error::ecdsa_error::create_context_failed); }
1423 if (EVP_PKEY_public_check(ctx.get()) != 1) {
1424 throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1425 }
1426#else
1427 std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
1428 if (!eckey) { throw error::ecdsa_exception(error::ecdsa_error::invalid_key); }
1429 if (EC_KEY_check_key(eckey.get()) == 0) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1430#endif
1431 }
1432
1433 static void check_private_key(EVP_PKEY* pkey) {
1434#ifdef JWT_OPENSSL_3_0
1435 std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ctx(
1436 EVP_PKEY_CTX_new_from_pkey(nullptr, pkey, nullptr), EVP_PKEY_CTX_free);
1437 if (!ctx) { throw error::ecdsa_exception(error::ecdsa_error::create_context_failed); }
1438 if (EVP_PKEY_private_check(ctx.get()) != 1) {
1439 throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1440 }
1441#else
1442 std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> eckey(EVP_PKEY_get1_EC_KEY(pkey), EC_KEY_free);
1443 if (!eckey) { throw error::ecdsa_exception(error::ecdsa_error::invalid_key); }
1444 if (EC_KEY_check_key(eckey.get()) == 0) throw error::ecdsa_exception(error::ecdsa_error::invalid_key);
1445#endif
1446 }
1447
1448 std::string der_to_p1363_signature(const std::string& der_signature, std::error_code& ec) const {
1449 const unsigned char* possl_signature = reinterpret_cast<const unsigned char*>(der_signature.data());
1450 std::unique_ptr<ECDSA_SIG, decltype(&ECDSA_SIG_free)> sig(
1451 d2i_ECDSA_SIG(nullptr, &possl_signature, static_cast<long>(der_signature.length())),
1452 ECDSA_SIG_free);
1453 if (!sig) {
1454 ec = error::signature_generation_error::signature_decoding_failed;
1455 return {};
1456 }
1457
1458#ifdef JWT_OPENSSL_1_0_0
1459 auto rr = helper::bn2raw(sig->r);
1460 auto rs = helper::bn2raw(sig->s);
1461#else
1462 const BIGNUM* r;
1463 const BIGNUM* s;
1464 ECDSA_SIG_get0(sig.get(), &r, &s);
1465 auto rr = helper::bn2raw(r);
1466 auto rs = helper::bn2raw(s);
1467#endif
1468 if (rr.size() > signature_length / 2 || rs.size() > signature_length / 2)
1469 throw std::logic_error("bignum size exceeded expected length");
1470 rr.insert(0, signature_length / 2 - rr.size(), '\0');
1471 rs.insert(0, signature_length / 2 - rs.size(), '\0');
1472 return rr + rs;
1473 }
1474
1475 std::string p1363_to_der_signature(const std::string& signature, std::error_code& ec) const {
1476 ec.clear();
1477 auto r = helper::raw2bn(signature.substr(0, signature.size() / 2), ec);
1478 if (ec) return {};
1479 auto s = helper::raw2bn(signature.substr(signature.size() / 2), ec);
1480 if (ec) return {};
1481
1482 ECDSA_SIG* psig;
1483#ifdef JWT_OPENSSL_1_0_0
1484 ECDSA_SIG sig;
1485 sig.r = r.get();
1486 sig.s = s.get();
1487 psig = &sig;
1488#else
1489 std::unique_ptr<ECDSA_SIG, decltype(&ECDSA_SIG_free)> sig(ECDSA_SIG_new(), ECDSA_SIG_free);
1490 if (!sig) {
1491 ec = error::signature_verification_error::create_context_failed;
1492 return {};
1493 }
1494 ECDSA_SIG_set0(sig.get(), r.release(), s.release());
1495 psig = sig.get();
1496#endif
1497
1498 int length = i2d_ECDSA_SIG(psig, nullptr);
1499 if (length < 0) {
1500 ec = error::signature_verification_error::signature_encoding_failed;
1501 return {};
1502 }
1503 std::string der_signature(length, '\0');
1504 unsigned char* psbuffer = (unsigned char*)der_signature.data();
1505 length = i2d_ECDSA_SIG(psig, &psbuffer);
1506 if (length < 0) {
1507 ec = error::signature_verification_error::signature_encoding_failed;
1508 return {};
1509 }
1510 der_signature.resize(length);
1511 return der_signature;
1512 }
1513
1515 helper::evp_pkey_handle pkey;
1517 const EVP_MD* (*md)();
1519 const std::string alg_name;
1521 const size_t signature_length;
1522 };
1523
1524#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1533 struct eddsa {
1544 eddsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1545 const std::string& private_key_password, std::string name)
1546 : alg_name(std::move(name)) {
1547 if (!private_key.empty()) {
1548 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1549 } else if (!public_key.empty()) {
1550 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1551 } else
1552 throw error::ecdsa_exception(error::ecdsa_error::load_key_bio_read);
1553 }
1560 std::string sign(const std::string& data, std::error_code& ec) const {
1561 ec.clear();
1562 auto ctx = helper::make_evp_md_ctx();
1563 if (!ctx) {
1564 ec = error::signature_generation_error::create_context_failed;
1565 return {};
1566 }
1567 if (!EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())) {
1568 ec = error::signature_generation_error::signinit_failed;
1569 return {};
1570 }
1571
1572 size_t len = EVP_PKEY_size(pkey.get());
1573 std::string res(len, '\0');
1574
1575// LibreSSL is the special kid in the block, as it does not support EVP_DigestSign.
1576// OpenSSL on the otherhand does not support using EVP_DigestSignUpdate for eddsa, which is why we end up with this
1577// mess.
1578#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1579 ERR_clear_error();
1580 if (EVP_DigestSignUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()), data.size()) !=
1581 1) {
1582 std::cout << ERR_error_string(ERR_get_error(), NULL) << std::endl;
1583 ec = error::signature_generation_error::signupdate_failed;
1584 return {};
1585 }
1586 if (EVP_DigestSignFinal(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len) != 1) {
1587 ec = error::signature_generation_error::signfinal_failed;
1588 return {};
1589 }
1590#else
1591 if (EVP_DigestSign(ctx.get(), reinterpret_cast<unsigned char*>(&res[0]), &len,
1592 reinterpret_cast<const unsigned char*>(data.data()), data.size()) != 1) {
1593 ec = error::signature_generation_error::signfinal_failed;
1594 return {};
1595 }
1596#endif
1597
1598 res.resize(len);
1599 return res;
1600 }
1601
1608 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1609 ec.clear();
1610 auto ctx = helper::make_evp_md_ctx();
1611 if (!ctx) {
1612 ec = error::signature_verification_error::create_context_failed;
1613 return;
1614 }
1615 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())) {
1616 ec = error::signature_verification_error::verifyinit_failed;
1617 return;
1618 }
1619// LibreSSL is the special kid in the block, as it does not support EVP_DigestVerify.
1620// OpenSSL on the otherhand does not support using EVP_DigestVerifyUpdate for eddsa, which is why we end up with this
1621// mess.
1622#if defined(LIBRESSL_VERSION_NUMBER) || defined(LIBWOLFSSL_VERSION_HEX)
1623 if (EVP_DigestVerifyUpdate(ctx.get(), reinterpret_cast<const unsigned char*>(data.data()),
1624 data.size()) != 1) {
1625 ec = error::signature_verification_error::verifyupdate_failed;
1626 return;
1627 }
1628 if (EVP_DigestVerifyFinal(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1629 signature.size()) != 1) {
1630 ec = error::signature_verification_error::verifyfinal_failed;
1631 return;
1632 }
1633#else
1634 auto res = EVP_DigestVerify(ctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
1635 signature.size(), reinterpret_cast<const unsigned char*>(data.data()),
1636 data.size());
1637 if (res != 1) {
1638 ec = error::signature_verification_error::verifyfinal_failed;
1639 return;
1640 }
1641#endif
1642 }
1647 std::string name() const { return alg_name; }
1648
1649 private:
1653 const std::string alg_name;
1654 };
1655#endif
1659 struct pss {
1669 pss(const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
1670 const std::string& private_key_password, const EVP_MD* (*md)(), std::string name)
1671 : md(md), alg_name(std::move(name)) {
1672 if (!private_key.empty()) {
1673 pkey = helper::load_private_key_from_string(private_key, private_key_password);
1674 } else if (!public_key.empty()) {
1675 pkey = helper::load_public_key_from_string(public_key, public_key_password);
1676 } else
1677 throw error::rsa_exception(error::rsa_error::no_key_provided);
1678 }
1679
1686 std::string sign(const std::string& data, std::error_code& ec) const {
1687 ec.clear();
1688 auto md_ctx = helper::make_evp_md_ctx();
1689 if (!md_ctx) {
1690 ec = error::signature_generation_error::create_context_failed;
1691 return {};
1692 }
1693 EVP_PKEY_CTX* ctx = nullptr;
1694 if (EVP_DigestSignInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1) {
1695 ec = error::signature_generation_error::signinit_failed;
1696 return {};
1697 }
1698 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
1699 ec = error::signature_generation_error::rsa_padding_failed;
1700 return {};
1701 }
1702// wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
1703// sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
1704#ifndef LIBWOLFSSL_VERSION_HEX
1705 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
1706 ec = error::signature_generation_error::set_rsa_pss_saltlen_failed;
1707 return {};
1708 }
1709#endif
1710 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1) {
1711 ec = error::signature_generation_error::digestupdate_failed;
1712 return {};
1713 }
1714
1715 size_t size = EVP_PKEY_size(pkey.get());
1716 std::string res(size, 0x00);
1717 if (EVP_DigestSignFinal(
1718 md_ctx.get(),
1719 (unsigned char*)res.data(), // NOLINT(google-readability-casting) requires `const_cast`
1720 &size) <= 0) {
1721 ec = error::signature_generation_error::signfinal_failed;
1722 return {};
1723 }
1724
1725 return res;
1726 }
1727
1734 void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
1735 ec.clear();
1736
1737 auto md_ctx = helper::make_evp_md_ctx();
1738 if (!md_ctx) {
1739 ec = error::signature_verification_error::create_context_failed;
1740 return;
1741 }
1742 EVP_PKEY_CTX* ctx = nullptr;
1743 if (EVP_DigestVerifyInit(md_ctx.get(), &ctx, md(), nullptr, pkey.get()) != 1) {
1744 ec = error::signature_verification_error::verifyinit_failed;
1745 return;
1746 }
1747 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
1748 ec = error::signature_generation_error::rsa_padding_failed;
1749 return;
1750 }
1751// wolfSSL does not require EVP_PKEY_CTX_set_rsa_pss_saltlen. The default behavior
1752// sets the salt length to the hash length. Unlike OpenSSL which exposes this functionality.
1753#ifndef LIBWOLFSSL_VERSION_HEX
1754 if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
1755 ec = error::signature_verification_error::set_rsa_pss_saltlen_failed;
1756 return;
1757 }
1758#endif
1759 if (EVP_DigestUpdate(md_ctx.get(), data.data(), data.size()) != 1) {
1760 ec = error::signature_verification_error::verifyupdate_failed;
1761 return;
1762 }
1763
1764 if (EVP_DigestVerifyFinal(md_ctx.get(), (unsigned char*)signature.data(), signature.size()) <= 0) {
1765 ec = error::signature_verification_error::verifyfinal_failed;
1766 return;
1767 }
1768 }
1773 std::string name() const { return alg_name; }
1774
1775 private:
1779 const EVP_MD* (*md)();
1781 const std::string alg_name;
1782 };
1783
1787 struct hs256 : public hmacsha {
1792 explicit hs256(std::string key) : hmacsha(std::move(key), EVP_sha256, "HS256") {}
1793 };
1797 struct hs384 : public hmacsha {
1802 explicit hs384(std::string key) : hmacsha(std::move(key), EVP_sha384, "HS384") {}
1803 };
1807 struct hs512 : public hmacsha {
1812 explicit hs512(std::string key) : hmacsha(std::move(key), EVP_sha512, "HS512") {}
1813 };
1819 struct rs256 : public rsa {
1828 explicit rs256(const std::string& public_key, const std::string& private_key = "",
1829 const std::string& public_key_password = "", const std::string& private_key_password = "")
1830 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "RS256") {}
1831 };
1835 struct rs384 : public rsa {
1843 explicit rs384(const std::string& public_key, const std::string& private_key = "",
1844 const std::string& public_key_password = "", const std::string& private_key_password = "")
1845 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "RS384") {}
1846 };
1850 struct rs512 : public rsa {
1858 explicit rs512(const std::string& public_key, const std::string& private_key = "",
1859 const std::string& public_key_password = "", const std::string& private_key_password = "")
1860 : rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "RS512") {}
1861 };
1865 struct es256 : public ecdsa {
1875 explicit es256(const std::string& public_key, const std::string& private_key = "",
1876 const std::string& public_key_password = "", const std::string& private_key_password = "")
1877 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "ES256", 64) {}
1878 };
1882 struct es384 : public ecdsa {
1892 explicit es384(const std::string& public_key, const std::string& private_key = "",
1893 const std::string& public_key_password = "", const std::string& private_key_password = "")
1894 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "ES384", 96) {}
1895 };
1899 struct es512 : public ecdsa {
1909 explicit es512(const std::string& public_key, const std::string& private_key = "",
1910 const std::string& public_key_password = "", const std::string& private_key_password = "")
1911 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "ES512", 132) {}
1912 };
1916 struct es256k : public ecdsa {
1925 explicit es256k(const std::string& public_key, const std::string& private_key = "",
1926 const std::string& public_key_password = "", const std::string& private_key_password = "")
1927 : ecdsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "ES256K", 64) {}
1928 };
1929
1930#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0)
1938 struct ed25519 : public eddsa {
1948 explicit ed25519(const std::string& public_key, const std::string& private_key = "",
1949 const std::string& public_key_password = "", const std::string& private_key_password = "")
1950 : eddsa(public_key, private_key, public_key_password, private_key_password, "EdDSA") {}
1951 };
1952
1960 struct ed448 : public eddsa {
1970 explicit ed448(const std::string& public_key, const std::string& private_key = "",
1971 const std::string& public_key_password = "", const std::string& private_key_password = "")
1972 : eddsa(public_key, private_key, public_key_password, private_key_password, "EdDSA") {}
1973 };
1974#endif
1975
1979 struct ps256 : public pss {
1987 explicit ps256(const std::string& public_key, const std::string& private_key = "",
1988 const std::string& public_key_password = "", const std::string& private_key_password = "")
1989 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "PS256") {}
1990 };
1994 struct ps384 : public pss {
2002 explicit ps384(const std::string& public_key, const std::string& private_key = "",
2003 const std::string& public_key_password = "", const std::string& private_key_password = "")
2004 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "PS384") {}
2005 };
2009 struct ps512 : public pss {
2017 explicit ps512(const std::string& public_key, const std::string& private_key = "",
2018 const std::string& public_key_password = "", const std::string& private_key_password = "")
2019 : pss(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "PS512") {}
2020 };
2021 } // namespace algorithm
2022
2026 namespace json {
2034 enum class type { boolean, integer, number, string, array, object };
2035 } // namespace json
2036
2037 namespace details {
2038#ifdef __cpp_lib_void_t
2039 template<typename... Ts>
2040 using void_t = std::void_t<Ts...>;
2041#else
2042 // https://en.cppreference.com/w/cpp/types/void_t
2043 template<typename... Ts>
2044 struct make_void {
2045 using type = void;
2046 };
2047
2048 template<typename... Ts>
2049 using void_t = typename make_void<Ts...>::type;
2050#endif
2051
2052#ifdef __cpp_lib_experimental_detect
2053 template<template<typename...> class _Op, typename... _Args>
2054 using is_detected = std::experimental::is_detected<_Op, _Args...>;
2055#else
2056 struct nonesuch {
2057 nonesuch() = delete;
2058 ~nonesuch() = delete;
2059 nonesuch(nonesuch const&) = delete;
2060 nonesuch(nonesuch const&&) = delete;
2061 void operator=(nonesuch const&) = delete;
2062 void operator=(nonesuch&&) = delete;
2063 };
2064
2065 // https://en.cppreference.com/w/cpp/experimental/is_detected
2066 template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
2067 struct detector {
2068 using value = std::false_type;
2069 using type = Default;
2070 };
2071
2072 template<class Default, template<class...> class Op, class... Args>
2073 struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
2074 using value = std::true_type;
2075 using type = Op<Args...>;
2076 };
2077
2078 template<template<class...> class Op, class... Args>
2079 using is_detected = typename detector<nonesuch, void, Op, Args...>::value;
2080#endif
2081
2082 template<typename T, typename Signature>
2083 using is_signature = typename std::is_same<T, Signature>;
2084
2085 template<typename traits_type, template<typename...> class Op, typename Signature>
2086 struct is_function_signature_detected {
2087 using type = Op<traits_type>;
2088 static constexpr auto value = is_detected<Op, traits_type>::value && std::is_function<type>::value &&
2089 is_signature<type, Signature>::value;
2090 };
2091
2092 template<typename traits_type, typename value_type>
2093 struct supports_get_type {
2094 template<typename T>
2095 using get_type_t = decltype(T::get_type);
2096
2097 static constexpr auto value =
2098 is_function_signature_detected<traits_type, get_type_t, json::type(const value_type&)>::value;
2099
2100 // Internal assertions for better feedback
2101 static_assert(value, "traits implementation must provide `jwt::json::type get_type(const value_type&)`");
2102 };
2103
2104#define JWT_CPP_JSON_TYPE_TYPE(TYPE) json_##TYPE_type
2105#define JWT_CPP_AS_TYPE_T(TYPE) as_##TYPE_t
2106#define JWT_CPP_SUPPORTS_AS(TYPE) \
2107 template<typename traits_type, typename value_type, typename JWT_CPP_JSON_TYPE_TYPE(TYPE)> \
2108 struct supports_as_##TYPE { \
2109 template<typename T> \
2110 using JWT_CPP_AS_TYPE_T(TYPE) = decltype(T::as_##TYPE); \
2111 \
2112 static constexpr auto value = \
2113 is_function_signature_detected<traits_type, JWT_CPP_AS_TYPE_T(TYPE), \
2114 JWT_CPP_JSON_TYPE_TYPE(TYPE)(const value_type&)>::value; \
2115 \
2116 static_assert(value, "traits implementation must provide `" #TYPE "_type as_" #TYPE "(const value_type&)`"); \
2117 }
2118
2119 JWT_CPP_SUPPORTS_AS(object);
2120 JWT_CPP_SUPPORTS_AS(array);
2121 JWT_CPP_SUPPORTS_AS(string);
2122 JWT_CPP_SUPPORTS_AS(number);
2123 JWT_CPP_SUPPORTS_AS(integer);
2124 JWT_CPP_SUPPORTS_AS(boolean);
2125
2126#undef JWT_CPP_JSON_TYPE_TYPE
2127#undef JWT_CPP_AS_TYPE_T
2128#undef JWT_CPP_SUPPORTS_AS
2129
2130 template<typename traits>
2131 struct is_valid_traits {
2132 static constexpr auto value =
2133 supports_get_type<traits, typename traits::value_type>::value &&
2134 supports_as_object<traits, typename traits::value_type, typename traits::object_type>::value &&
2135 supports_as_array<traits, typename traits::value_type, typename traits::array_type>::value &&
2136 supports_as_string<traits, typename traits::value_type, typename traits::string_type>::value &&
2137 supports_as_number<traits, typename traits::value_type, typename traits::number_type>::value &&
2138 supports_as_integer<traits, typename traits::value_type, typename traits::integer_type>::value &&
2139 supports_as_boolean<traits, typename traits::value_type, typename traits::boolean_type>::value;
2140 };
2141
2142 template<typename value_type>
2143 struct is_valid_json_value {
2144 static constexpr auto value =
2145 std::is_default_constructible<value_type>::value &&
2146 std::is_constructible<value_type, const value_type&>::value && // a more generic is_copy_constructible
2147 std::is_move_constructible<value_type>::value && std::is_assignable<value_type, value_type>::value &&
2148 std::is_copy_assignable<value_type>::value && std::is_move_assignable<value_type>::value;
2149 // TODO(prince-chrismc): Stream operators
2150 };
2151
2152 // https://stackoverflow.com/a/53967057/8480874
2153 template<typename T, typename = void>
2154 struct is_iterable : std::false_type {};
2155
2156 template<typename T>
2157 struct is_iterable<T, void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>())),
2158#if __cplusplus > 201402L
2159 decltype(std::cbegin(std::declval<T>())), decltype(std::cend(std::declval<T>()))
2160#else
2161 decltype(std::begin(std::declval<const T>())),
2162 decltype(std::end(std::declval<const T>()))
2163#endif
2164 >> : std::true_type {
2165 };
2166
2167#if __cplusplus > 201703L
2168 template<typename T>
2169 inline constexpr bool is_iterable_v = is_iterable<T>::value;
2170#endif
2171
2172 template<typename object_type, typename string_type>
2173 using is_count_signature = typename std::is_integral<decltype(std::declval<const object_type>().count(
2174 std::declval<const string_type>()))>;
2175
2176 template<typename object_type, typename string_type, typename = void>
2177 struct is_subcription_operator_signature : std::false_type {};
2178
2179 template<typename object_type, typename string_type>
2180 struct is_subcription_operator_signature<
2181 object_type, string_type,
2182 void_t<decltype(std::declval<object_type>().operator[](std::declval<string_type>()))>> : std::true_type {
2183 // TODO(prince-chrismc): I am not convienced this is meaningful anymore
2184 static_assert(
2185 value,
2186 "object_type must implementate the subscription operator '[]' taking string_type as an argument");
2187 };
2188
2189 template<typename object_type, typename value_type, typename string_type>
2190 using is_at_const_signature =
2191 typename std::is_same<decltype(std::declval<const object_type>().at(std::declval<const string_type>())),
2192 const value_type&>;
2193
2194 template<typename value_type, typename string_type, typename object_type>
2195 struct is_valid_json_object {
2196 template<typename T>
2197 using mapped_type_t = typename T::mapped_type;
2198 template<typename T>
2199 using key_type_t = typename T::key_type;
2200 template<typename T>
2201 using iterator_t = typename T::iterator;
2202 template<typename T>
2203 using const_iterator_t = typename T::const_iterator;
2204
2205 static constexpr auto value =
2206 std::is_constructible<value_type, object_type>::value &&
2207 is_detected<mapped_type_t, object_type>::value &&
2208 std::is_same<typename object_type::mapped_type, value_type>::value &&
2209 is_detected<key_type_t, object_type>::value &&
2210 (std::is_same<typename object_type::key_type, string_type>::value ||
2211 std::is_constructible<typename object_type::key_type, string_type>::value) &&
2212 is_detected<iterator_t, object_type>::value && is_detected<const_iterator_t, object_type>::value &&
2213 is_iterable<object_type>::value && is_count_signature<object_type, string_type>::value &&
2214 is_subcription_operator_signature<object_type, string_type>::value &&
2215 is_at_const_signature<object_type, value_type, string_type>::value;
2216 };
2217
2218 template<typename value_type, typename array_type>
2219 struct is_valid_json_array {
2220 template<typename T>
2221 using value_type_t = typename T::value_type;
2222
2223 static constexpr auto value = std::is_constructible<value_type, array_type>::value &&
2224 is_iterable<array_type>::value &&
2225 is_detected<value_type_t, array_type>::value &&
2226 std::is_same<typename array_type::value_type, value_type>::value;
2227 };
2228
2229 template<typename string_type, typename integer_type>
2230 using is_substr_start_end_index_signature =
2231 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>(),
2232 std::declval<integer_type>())),
2233 string_type>;
2234
2235 template<typename string_type, typename integer_type>
2236 using is_substr_start_index_signature =
2237 typename std::is_same<decltype(std::declval<string_type>().substr(std::declval<integer_type>())),
2238 string_type>;
2239
2240 template<typename string_type>
2241 using is_std_operate_plus_signature =
2242 typename std::is_same<decltype(std::operator+(std::declval<string_type>(), std::declval<string_type>())),
2243 string_type>;
2244
2245 template<typename value_type, typename string_type, typename integer_type>
2246 struct is_valid_json_string {
2247 static constexpr auto substr = is_substr_start_end_index_signature<string_type, integer_type>::value &&
2248 is_substr_start_index_signature<string_type, integer_type>::value;
2249 static_assert(substr, "string_type must have a substr method taking only a start index and an overload "
2250 "taking a start and end index, both must return a string_type");
2251
2252 static constexpr auto operator_plus = is_std_operate_plus_signature<string_type>::value;
2253 static_assert(operator_plus,
2254 "string_type must have a '+' operator implemented which returns the concatenated string");
2255
2256 static constexpr auto value =
2257 std::is_constructible<value_type, string_type>::value && substr && operator_plus;
2258 };
2259
2260 template<typename value_type, typename number_type>
2261 struct is_valid_json_number {
2262 static constexpr auto value =
2263 std::is_floating_point<number_type>::value && std::is_constructible<value_type, number_type>::value;
2264 };
2265
2266 template<typename value_type, typename integer_type>
2267 struct is_valid_json_integer {
2268 static constexpr auto value = std::is_signed<integer_type>::value &&
2269 !std::is_floating_point<integer_type>::value &&
2270 std::is_constructible<value_type, integer_type>::value;
2271 };
2272 template<typename value_type, typename boolean_type>
2273 struct is_valid_json_boolean {
2274 static constexpr auto value = std::is_convertible<boolean_type, bool>::value &&
2275 std::is_constructible<value_type, boolean_type>::value;
2276 };
2277
2278 template<typename value_type, typename object_type, typename array_type, typename string_type,
2279 typename number_type, typename integer_type, typename boolean_type>
2280 struct is_valid_json_types {
2281 // Internal assertions for better feedback
2282 static_assert(is_valid_json_value<value_type>::value,
2283 "value_type must meet basic requirements, default constructor, copyable, moveable");
2284 static_assert(is_valid_json_object<value_type, string_type, object_type>::value,
2285 "object_type must be a string_type to value_type container");
2286 static_assert(is_valid_json_array<value_type, array_type>::value,
2287 "array_type must be a container of value_type");
2288
2289 static constexpr auto value = is_valid_json_value<value_type>::value &&
2290 is_valid_json_object<value_type, string_type, object_type>::value &&
2291 is_valid_json_array<value_type, array_type>::value &&
2292 is_valid_json_string<value_type, string_type, integer_type>::value &&
2293 is_valid_json_number<value_type, number_type>::value &&
2294 is_valid_json_integer<value_type, integer_type>::value &&
2295 is_valid_json_boolean<value_type, boolean_type>::value;
2296 };
2297 } // namespace details
2298
2306 template<typename json_traits>
2314 static_assert(std::is_same<typename json_traits::string_type, std::string>::value ||
2315 std::is_convertible<typename json_traits::string_type, std::string>::value ||
2316 std::is_constructible<typename json_traits::string_type, std::string>::value,
2317 "string_type must be a std::string, convertible to a std::string, or construct a std::string.");
2318
2319 static_assert(
2320 details::is_valid_json_types<typename json_traits::value_type, typename json_traits::object_type,
2321 typename json_traits::array_type, typename json_traits::string_type,
2322 typename json_traits::number_type, typename json_traits::integer_type,
2323 typename json_traits::boolean_type>::value,
2324 "must satisfy json container requirements");
2325 static_assert(details::is_valid_traits<json_traits>::value, "traits must satisfy requirements");
2326
2327 typename json_traits::value_type val;
2328
2329 public:
2333 using set_t = std::set<typename json_traits::string_type>;
2334
2335 basic_claim() = default;
2336 basic_claim(const basic_claim&) = default;
2337 basic_claim(basic_claim&&) = default;
2338 basic_claim& operator=(const basic_claim&) = default;
2339 basic_claim& operator=(basic_claim&&) = default;
2340 ~basic_claim() = default;
2341
2342 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s) : val(std::move(s)) {}
2343 JWT_CLAIM_EXPLICIT basic_claim(const date& d)
2344 : val(typename json_traits::integer_type(std::chrono::system_clock::to_time_t(d))) {}
2345 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a) : val(std::move(a)) {}
2346 JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v) : val(std::move(v)) {}
2347 JWT_CLAIM_EXPLICIT basic_claim(const set_t& s) : val(typename json_traits::array_type(s.begin(), s.end())) {}
2348 template<typename Iterator>
2349 basic_claim(Iterator begin, Iterator end) : val(typename json_traits::array_type(begin, end)) {}
2350
2355 typename json_traits::value_type to_json() const { return val; }
2356
2361 std::istream& operator>>(std::istream& is) { return is >> val; }
2362
2367 std::ostream& operator<<(std::ostream& os) { return os << val; }
2368
2374 json::type get_type() const { return json_traits::get_type(val); }
2375
2381 typename json_traits::string_type as_string() const { return json_traits::as_string(val); }
2382
2391 date as_date() const {
2392 using std::chrono::system_clock;
2393 if (get_type() == json::type::number) return system_clock::from_time_t(std::round(as_number()));
2394 return system_clock::from_time_t(as_integer());
2395 }
2396
2402 typename json_traits::array_type as_array() const { return json_traits::as_array(val); }
2403
2409 set_t as_set() const {
2410 set_t res;
2411 for (const auto& e : json_traits::as_array(val)) {
2412 res.insert(json_traits::as_string(e));
2413 }
2414 return res;
2415 }
2416
2422 typename json_traits::integer_type as_integer() const { return json_traits::as_integer(val); }
2423
2429 typename json_traits::boolean_type as_boolean() const { return json_traits::as_boolean(val); }
2430
2436 typename json_traits::number_type as_number() const { return json_traits::as_number(val); }
2437 };
2438
2439 namespace error {
2443 struct invalid_json_exception : public std::runtime_error {
2444 invalid_json_exception() : runtime_error("invalid json") {}
2445 };
2449 struct claim_not_present_exception : public std::out_of_range {
2450 claim_not_present_exception() : out_of_range("claim not found") {}
2451 };
2452 } // namespace error
2453
2454 namespace details {
2455 template<typename json_traits>
2456 struct map_of_claims {
2457 typename json_traits::object_type claims;
2458 using basic_claim_t = basic_claim<json_traits>;
2459 using iterator = typename json_traits::object_type::iterator;
2460 using const_iterator = typename json_traits::object_type::const_iterator;
2461
2462 map_of_claims() = default;
2463 map_of_claims(const map_of_claims&) = default;
2464 map_of_claims(map_of_claims&&) = default;
2465 map_of_claims& operator=(const map_of_claims&) = default;
2466 map_of_claims& operator=(map_of_claims&&) = default;
2467
2468 map_of_claims(typename json_traits::object_type json) : claims(std::move(json)) {}
2469
2470 iterator begin() { return claims.begin(); }
2471 iterator end() { return claims.end(); }
2472 const_iterator cbegin() const { return claims.begin(); }
2473 const_iterator cend() const { return claims.end(); }
2474 const_iterator begin() const { return claims.begin(); }
2475 const_iterator end() const { return claims.end(); }
2476
2485 static typename json_traits::object_type parse_claims(const typename json_traits::string_type& str) {
2486 typename json_traits::value_type val;
2487 if (!json_traits::parse(val, str)) throw error::invalid_json_exception();
2488
2489 return json_traits::as_object(val);
2490 };
2491
2496 bool has_claim(const typename json_traits::string_type& name) const noexcept {
2497 return claims.count(name) != 0;
2498 }
2499
2507 basic_claim_t get_claim(const typename json_traits::string_type& name) const {
2508 if (!has_claim(name)) throw error::claim_not_present_exception();
2509 return basic_claim_t{claims.at(name)};
2510 }
2511 };
2512 } // namespace details
2513
2518 template<typename json_traits>
2519 class payload {
2520 protected:
2521 details::map_of_claims<json_traits> payload_claims;
2522
2523 public:
2525
2530 bool has_issuer() const noexcept { return has_payload_claim("iss"); }
2535 bool has_subject() const noexcept { return has_payload_claim("sub"); }
2540 bool has_audience() const noexcept { return has_payload_claim("aud"); }
2545 bool has_expires_at() const noexcept { return has_payload_claim("exp"); }
2550 bool has_not_before() const noexcept { return has_payload_claim("nbf"); }
2555 bool has_issued_at() const noexcept { return has_payload_claim("iat"); }
2560 bool has_id() const noexcept { return has_payload_claim("jti"); }
2567 typename json_traits::string_type get_issuer() const { return get_payload_claim("iss").as_string(); }
2574 typename json_traits::string_type get_subject() const { return get_payload_claim("sub").as_string(); }
2582 auto aud = get_payload_claim("aud");
2583 if (aud.get_type() == json::type::string) return {aud.as_string()};
2584
2585 return aud.as_set();
2586 }
2593 date get_expires_at() const { return get_payload_claim("exp").as_date(); }
2600 date get_not_before() const { return get_payload_claim("nbf").as_date(); }
2607 date get_issued_at() const { return get_payload_claim("iat").as_date(); }
2614 typename json_traits::string_type get_id() const { return get_payload_claim("jti").as_string(); }
2619 bool has_payload_claim(const typename json_traits::string_type& name) const noexcept {
2620 return payload_claims.has_claim(name);
2621 }
2627 basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const {
2628 return payload_claims.get_claim(name);
2629 }
2630 };
2631
2636 template<typename json_traits>
2637 class header {
2638 protected:
2639 details::map_of_claims<json_traits> header_claims;
2640
2641 public:
2647 bool has_algorithm() const noexcept { return has_header_claim("alg"); }
2652 bool has_type() const noexcept { return has_header_claim("typ"); }
2657 bool has_content_type() const noexcept { return has_header_claim("cty"); }
2662 bool has_key_id() const noexcept { return has_header_claim("kid"); }
2669 typename json_traits::string_type get_algorithm() const { return get_header_claim("alg").as_string(); }
2676 typename json_traits::string_type get_type() const { return get_header_claim("typ").as_string(); }
2683 typename json_traits::string_type get_content_type() const { return get_header_claim("cty").as_string(); }
2690 typename json_traits::string_type get_key_id() const { return get_header_claim("kid").as_string(); }
2695 bool has_header_claim(const typename json_traits::string_type& name) const noexcept {
2696 return header_claims.has_claim(name);
2697 }
2703 basic_claim_t get_header_claim(const typename json_traits::string_type& name) const {
2704 return header_claims.get_claim(name);
2705 }
2706 };
2707
2711 template<typename json_traits>
2712 class decoded_jwt : public header<json_traits>, public payload<json_traits> {
2713 protected:
2715 typename json_traits::string_type token;
2717 typename json_traits::string_type header;
2719 typename json_traits::string_type header_base64;
2721 typename json_traits::string_type payload;
2723 typename json_traits::string_type payload_base64;
2725 typename json_traits::string_type signature;
2727 typename json_traits::string_type signature_base64;
2728
2729 public:
2731#ifndef JWT_DISABLE_BASE64
2741 JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type& token)
2742 : decoded_jwt(token, [](const typename json_traits::string_type& str) {
2743 return base::decode<alphabet::base64url>(base::pad<alphabet::base64url>(str));
2744 }) {}
2745#endif
2757 template<typename Decode>
2758 decoded_jwt(const typename json_traits::string_type& token, Decode decode) : token(token) {
2759 auto hdr_end = token.find('.');
2760 if (hdr_end == json_traits::string_type::npos) throw std::invalid_argument("invalid token supplied");
2761 auto payload_end = token.find('.', hdr_end + 1);
2762 if (payload_end == json_traits::string_type::npos) throw std::invalid_argument("invalid token supplied");
2763 header_base64 = token.substr(0, hdr_end);
2764 payload_base64 = token.substr(hdr_end + 1, payload_end - hdr_end - 1);
2765 signature_base64 = token.substr(payload_end + 1);
2766
2770
2771 this->header_claims = details::map_of_claims<json_traits>::parse_claims(header);
2772 this->payload_claims = details::map_of_claims<json_traits>::parse_claims(payload);
2773 }
2774
2779 const typename json_traits::string_type& get_token() const noexcept { return token; }
2784 const typename json_traits::string_type& get_header() const noexcept { return header; }
2789 const typename json_traits::string_type& get_payload() const noexcept { return payload; }
2794 const typename json_traits::string_type& get_signature() const noexcept { return signature; }
2799 const typename json_traits::string_type& get_header_base64() const noexcept { return header_base64; }
2804 const typename json_traits::string_type& get_payload_base64() const noexcept { return payload_base64; }
2809 const typename json_traits::string_type& get_signature_base64() const noexcept { return signature_base64; }
2814 typename json_traits::object_type get_payload_json() const { return this->payload_claims.claims; }
2819 typename json_traits::object_type get_header_json() const { return this->header_claims.claims; }
2827 basic_claim_t get_payload_claim(const typename json_traits::string_type& name) const {
2828 return this->payload_claims.get_claim(name);
2829 }
2837 basic_claim_t get_header_claim(const typename json_traits::string_type& name) const {
2838 return this->header_claims.get_claim(name);
2839 }
2840 };
2841
2846 template<typename Clock, typename json_traits>
2847 class builder {
2848 typename json_traits::object_type header_claims;
2849 typename json_traits::object_type payload_claims;
2850
2852 Clock clock;
2853
2854 public:
2859 JWT_CLAIM_EXPLICIT builder(Clock c) : clock(c) {}
2866 builder& set_header_claim(const typename json_traits::string_type& id, typename json_traits::value_type c) {
2867 header_claims[id] = std::move(c);
2868 return *this;
2869 }
2870
2877 builder& set_header_claim(const typename json_traits::string_type& id, basic_claim<json_traits> c) {
2878 header_claims[id] = c.to_json();
2879 return *this;
2880 }
2887 builder& set_payload_claim(const typename json_traits::string_type& id, typename json_traits::value_type c) {
2888 payload_claims[id] = std::move(c);
2889 return *this;
2890 }
2897 builder& set_payload_claim(const typename json_traits::string_type& id, basic_claim<json_traits> c) {
2898 payload_claims[id] = c.to_json();
2899 return *this;
2900 }
2908 builder& set_algorithm(typename json_traits::string_type str) {
2909 return set_header_claim("alg", typename json_traits::value_type(str));
2910 }
2916 builder& set_type(typename json_traits::string_type str) {
2917 return set_header_claim("typ", typename json_traits::value_type(str));
2918 }
2924 builder& set_content_type(typename json_traits::string_type str) {
2925 return set_header_claim("cty", typename json_traits::value_type(str));
2926 }
2933 builder& set_key_id(typename json_traits::string_type str) {
2934 return set_header_claim("kid", typename json_traits::value_type(str));
2935 }
2941 builder& set_issuer(typename json_traits::string_type str) {
2942 return set_payload_claim("iss", typename json_traits::value_type(str));
2943 }
2949 builder& set_subject(typename json_traits::string_type str) {
2950 return set_payload_claim("sub", typename json_traits::value_type(str));
2951 }
2957 builder& set_audience(typename json_traits::array_type a) {
2958 return set_payload_claim("aud", typename json_traits::value_type(a));
2959 }
2965 builder& set_audience(typename json_traits::string_type aud) {
2966 return set_payload_claim("aud", typename json_traits::value_type(aud));
2967 }
2979 template<class Rep>
2980 builder& set_expires_in(const std::chrono::duration<Rep>& d) {
2981 return set_payload_claim("exp", basic_claim<json_traits>(clock.now() + d));
2982 }
2999 builder& set_issued_now() { return set_issued_at(clock.now()); }
3005 builder& set_id(const typename json_traits::string_type& str) {
3006 return set_payload_claim("jti", typename json_traits::value_type(str));
3007 }
3008
3020 template<typename Algo, typename Encode>
3021 typename json_traits::string_type sign(const Algo& algo, Encode encode) const {
3022 std::error_code ec;
3023 auto res = sign(algo, encode, ec);
3025 return res;
3026 }
3027#ifndef JWT_DISABLE_BASE64
3036 template<typename Algo>
3037 typename json_traits::string_type sign(const Algo& algo) const {
3038 std::error_code ec;
3039 auto res = sign(algo, ec);
3041 return res;
3042 }
3043#endif
3044
3057 template<typename Algo, typename Encode>
3058 typename json_traits::string_type sign(const Algo& algo, Encode encode, std::error_code& ec) const {
3059 // make a copy such that a builder can be re-used
3060 typename json_traits::object_type obj_header = header_claims;
3061 if (header_claims.count("alg") == 0) obj_header["alg"] = typename json_traits::value_type(algo.name());
3062
3063 const auto header = encode(json_traits::serialize(typename json_traits::value_type(obj_header)));
3064 const auto payload = encode(json_traits::serialize(typename json_traits::value_type(payload_claims)));
3065 const auto token = header + "." + payload;
3066
3067 auto signature = algo.sign(token, ec);
3068 if (ec) return {};
3069
3070 return token + "." + encode(signature);
3071 }
3072#ifndef JWT_DISABLE_BASE64
3082 template<typename Algo>
3083 typename json_traits::string_type sign(const Algo& algo, std::error_code& ec) const {
3084 return sign(
3085 algo,
3086 [](const typename json_traits::string_type& data) {
3087 return base::trim<alphabet::base64url>(base::encode<alphabet::base64url>(data));
3088 },
3089 ec);
3090 }
3091#endif
3092 };
3093
3094 namespace verify_ops {
3098 template<typename json_traits>
3100 verify_context(date ctime, const decoded_jwt<json_traits>& j, size_t l)
3101 : current_time(ctime), jwt(j), default_leeway(l) {}
3108
3110 typename json_traits::string_type claim_key{};
3111
3118 basic_claim<json_traits> get_claim(bool in_header, std::error_code& ec) const {
3119 if (in_header) {
3120 if (!jwt.has_header_claim(claim_key)) {
3121 ec = error::token_verification_error::missing_claim;
3122 return {};
3123 }
3124 return jwt.get_header_claim(claim_key);
3125 } else {
3126 if (!jwt.has_payload_claim(claim_key)) {
3127 ec = error::token_verification_error::missing_claim;
3128 return {};
3129 }
3130 return jwt.get_payload_claim(claim_key);
3131 }
3132 }
3140 basic_claim<json_traits> get_claim(bool in_header, json::type t, std::error_code& ec) const {
3141 auto c = get_claim(in_header, ec);
3142 if (ec) return {};
3143 if (c.get_type() != t) {
3144 ec = error::token_verification_error::claim_type_missmatch;
3145 return {};
3146 }
3147 return c;
3148 }
3154 basic_claim<json_traits> get_claim(std::error_code& ec) const { return get_claim(false, ec); }
3161 basic_claim<json_traits> get_claim(json::type t, std::error_code& ec) const {
3162 return get_claim(false, t, ec);
3163 }
3164 };
3165
3169 template<typename json_traits, bool in_header = false>
3171 const basic_claim<json_traits> expected;
3172 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3173 auto jc = ctx.get_claim(in_header, expected.get_type(), ec);
3174 if (ec) return;
3175 const bool matches = [&]() {
3176 switch (expected.get_type()) {
3177 case json::type::boolean: return expected.as_boolean() == jc.as_boolean();
3178 case json::type::integer: return expected.as_integer() == jc.as_integer();
3179 case json::type::number: return expected.as_number() == jc.as_number();
3180 case json::type::string: return expected.as_string() == jc.as_string();
3181 case json::type::array:
3182 case json::type::object:
3183 return json_traits::serialize(expected.to_json()) == json_traits::serialize(jc.to_json());
3184 default: throw std::logic_error("internal error, should be unreachable");
3185 }
3186 }();
3187 if (!matches) {
3188 ec = error::token_verification_error::claim_value_missmatch;
3189 return;
3190 }
3191 }
3192 };
3193
3198 template<typename json_traits, bool in_header = false>
3200 const size_t leeway;
3201 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3202 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3203 if (ec) return;
3204 auto c = jc.as_date();
3205 if (ctx.current_time > c + std::chrono::seconds(leeway)) {
3206 ec = error::token_verification_error::token_expired;
3207 }
3208 }
3209 };
3210
3215 template<typename json_traits, bool in_header = false>
3217 const size_t leeway;
3218 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3219 auto jc = ctx.get_claim(in_header, json::type::integer, ec);
3220 if (ec) return;
3221 auto c = jc.as_date();
3222 if (ctx.current_time < c - std::chrono::seconds(leeway)) {
3223 ec = error::token_verification_error::token_expired;
3224 }
3225 }
3226 };
3227
3233 template<typename json_traits, bool in_header = false>
3235 const typename basic_claim<json_traits>::set_t expected;
3236 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3237 auto c = ctx.get_claim(in_header, ec);
3238 if (ec) return;
3239 if (c.get_type() == json::type::string) {
3240 if (expected.size() != 1 || *expected.begin() != c.as_string()) {
3241 ec = error::token_verification_error::audience_missmatch;
3242 return;
3243 }
3244 } else if (c.get_type() == json::type::array) {
3245 auto jc = c.as_set();
3246 for (auto& e : expected) {
3247 if (jc.find(e) == jc.end()) {
3248 ec = error::token_verification_error::audience_missmatch;
3249 return;
3250 }
3251 }
3252 } else {
3253 ec = error::token_verification_error::claim_type_missmatch;
3254 return;
3255 }
3256 }
3257 };
3258
3262 template<typename json_traits, bool in_header = false>
3264 const typename json_traits::string_type expected;
3265 std::locale locale;
3266 insensitive_string_claim(const typename json_traits::string_type& e, std::locale loc)
3267 : expected(to_lower_unicode(e, loc)), locale(loc) {}
3268
3269 void operator()(const verify_context<json_traits>& ctx, std::error_code& ec) const {
3270 const auto c = ctx.get_claim(in_header, json::type::string, ec);
3271 if (ec) return;
3272 if (to_lower_unicode(c.as_string(), locale) != expected) {
3273 ec = error::token_verification_error::claim_value_missmatch;
3274 }
3275 }
3276
3277 static std::string to_lower_unicode(const std::string& str, const std::locale& loc) {
3278 std::mbstate_t state = std::mbstate_t();
3279 const char* in_next = str.data();
3280 const char* in_end = str.data() + str.size();
3281 std::wstring wide;
3282 wide.reserve(str.size());
3283
3284 while (in_next != in_end) {
3285 wchar_t wc;
3286 std::size_t result = std::mbrtowc(&wc, in_next, in_end - in_next, &state);
3287 if (result == static_cast<std::size_t>(-1)) {
3288 throw std::runtime_error("encoding error: " + std::string(std::strerror(errno)));
3289 } else if (result == static_cast<std::size_t>(-2)) {
3290 throw std::runtime_error("conversion error: next bytes constitute an incomplete, but so far "
3291 "valid, multibyte character.");
3292 }
3293 in_next += result;
3294 wide.push_back(wc);
3295 }
3296
3297 auto& f = std::use_facet<std::ctype<wchar_t>>(loc);
3298 f.tolower(&wide[0], &wide[0] + wide.size());
3299
3300 std::string out;
3301 out.reserve(wide.size());
3302 for (wchar_t wc : wide) {
3303 char mb[MB_LEN_MAX];
3304 std::size_t n = std::wcrtomb(mb, wc, &state);
3305 if (n != static_cast<std::size_t>(-1)) out.append(mb, n);
3306 }
3307
3308 return out;
3309 }
3310 };
3311 } // namespace verify_ops
3312
3317 template<typename Clock, typename json_traits>
3318 class verifier {
3319 public:
3331 std::function<void(const verify_ops::verify_context<json_traits>&, std::error_code& ec)>;
3332
3333 private:
3334 struct algo_base {
3335 virtual ~algo_base() = default;
3336 virtual void verify(const std::string& data, const std::string& sig, std::error_code& ec) = 0;
3337 };
3338 template<typename T>
3339 struct algo : public algo_base {
3340 T alg;
3341 explicit algo(T a) : alg(a) {}
3342 void verify(const std::string& data, const std::string& sig, std::error_code& ec) override {
3343 alg.verify(data, sig, ec);
3344 }
3345 };
3347 std::unordered_map<typename json_traits::string_type, verify_check_fn_t> claims;
3349 size_t default_leeway = 0;
3351 Clock clock;
3353 std::unordered_map<std::string, std::shared_ptr<algo_base>> algs;
3354
3355 public:
3360 explicit verifier(Clock c) : clock(c) {
3361 claims["exp"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3362 if (!ctx.jwt.has_expires_at()) return;
3363 auto exp = ctx.jwt.get_expires_at();
3364 if (ctx.current_time > exp + std::chrono::seconds(ctx.default_leeway)) {
3365 ec = error::token_verification_error::token_expired;
3366 }
3367 };
3368 claims["iat"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3369 if (!ctx.jwt.has_issued_at()) return;
3370 auto iat = ctx.jwt.get_issued_at();
3371 if (ctx.current_time < iat - std::chrono::seconds(ctx.default_leeway)) {
3372 ec = error::token_verification_error::token_expired;
3373 }
3374 };
3375 claims["nbf"] = [](const verify_ops::verify_context<json_traits>& ctx, std::error_code& ec) {
3376 if (!ctx.jwt.has_not_before()) return;
3377 auto nbf = ctx.jwt.get_not_before();
3378 if (ctx.current_time < nbf - std::chrono::seconds(ctx.default_leeway)) {
3379 ec = error::token_verification_error::token_expired;
3380 }
3381 };
3382 }
3383
3390 default_leeway = leeway;
3391 return *this;
3392 }
3401 return *this;
3402 }
3411 return *this;
3412 }
3421 return *this;
3422 }
3423
3435 verifier& with_type(const typename json_traits::string_type& type, std::locale locale = std::locale{}) {
3436 return with_claim("typ", verify_ops::insensitive_string_claim<json_traits, true>{type, std::move(locale)});
3437 }
3438
3445 verifier& with_issuer(const typename json_traits::string_type& iss) {
3446 return with_claim("iss", basic_claim_t(iss));
3447 }
3448
3455 verifier& with_subject(const typename json_traits::string_type& sub) {
3456 return with_claim("sub", basic_claim_t(sub));
3457 }
3465 claims["aud"] = verify_ops::is_subset_claim<json_traits>{aud};
3466 return *this;
3467 }
3474 verifier& with_audience(const typename json_traits::string_type& aud) {
3475 typename basic_claim_t::set_t s;
3476 s.insert(aud);
3477 return with_audience(s);
3478 }
3485 verifier& with_id(const typename json_traits::string_type& id) { return with_claim("jti", basic_claim_t(id)); }
3486
3498 verifier& with_claim(const typename json_traits::string_type& name, verify_check_fn_t fn) {
3499 claims[name] = fn;
3500 return *this;
3501 }
3502
3513 verifier& with_claim(const typename json_traits::string_type& name, basic_claim_t c) {
3515 }
3516
3530 template<typename Algorithm>
3531 verifier& allow_algorithm(Algorithm alg) {
3532 algs[alg.name()] = std::make_shared<algo<Algorithm>>(alg);
3533 return *this;
3534 }
3535
3542 std::error_code ec;
3543 verify(jwt, ec);
3545 }
3551 void verify(const decoded_jwt<json_traits>& jwt, std::error_code& ec) const {
3552 ec.clear();
3553 const typename json_traits::string_type data = jwt.get_header_base64() + "." + jwt.get_payload_base64();
3554 const typename json_traits::string_type sig = jwt.get_signature();
3555 const std::string algo = jwt.get_algorithm();
3556 if (algs.count(algo) == 0) {
3557 ec = error::token_verification_error::wrong_algorithm;
3558 return;
3559 }
3560 algs.at(algo)->verify(data, sig, ec);
3561 if (ec) return;
3562
3563 verify_ops::verify_context<json_traits> ctx{clock.now(), jwt, default_leeway};
3564 for (auto& c : claims) {
3565 ctx.claim_key = c.first;
3566 c.second(ctx, ec);
3567 if (ec) return;
3568 }
3569 }
3570 };
3571
3580 template<typename json_traits>
3581 class jwk {
3583 const details::map_of_claims<json_traits> jwk_claims;
3584
3585 public:
3586 JWT_CLAIM_EXPLICIT jwk(const typename json_traits::string_type& str)
3587 : jwk_claims(details::map_of_claims<json_traits>::parse_claims(str)) {}
3588
3589 JWT_CLAIM_EXPLICIT jwk(const typename json_traits::value_type& json)
3590 : jwk_claims(json_traits::as_object(json)) {}
3591
3600 typename json_traits::string_type get_key_type() const { return get_jwk_claim("kty").as_string(); }
3601
3608 typename json_traits::string_type get_use() const { return get_jwk_claim("use").as_string(); }
3609
3616 typename basic_claim_t::set_t get_key_operations() const { return get_jwk_claim("key_ops").as_set(); }
3617
3624 typename json_traits::string_type get_algorithm() const { return get_jwk_claim("alg").as_string(); }
3625
3632 typename json_traits::string_type get_key_id() const { return get_jwk_claim("kid").as_string(); }
3633
3644 typename json_traits::string_type get_curve() const { return get_jwk_claim("crv").as_string(); }
3645
3652 typename json_traits::array_type get_x5c() const { return get_jwk_claim("x5c").as_array(); };
3653
3660 typename json_traits::string_type get_x5u() const { return get_jwk_claim("x5u").as_string(); };
3661
3668 typename json_traits::string_type get_x5t() const { return get_jwk_claim("x5t").as_string(); };
3669
3676 typename json_traits::string_type get_x5t_sha256() const { return get_jwk_claim("x5t#S256").as_string(); };
3677
3684 typename json_traits::string_type get_x5c_key_value() const {
3685 auto x5c_array = get_jwk_claim("x5c").as_array();
3686 if (x5c_array.size() == 0) throw error::claim_not_present_exception();
3687
3688 return json_traits::as_string(x5c_array.front());
3689 };
3690
3695 bool has_key_type() const noexcept { return has_jwk_claim("kty"); }
3696
3701 bool has_use() const noexcept { return has_jwk_claim("use"); }
3702
3707 bool has_key_operations() const noexcept { return has_jwk_claim("key_ops"); }
3708
3713 bool has_algorithm() const noexcept { return has_jwk_claim("alg"); }
3714
3719 bool has_curve() const noexcept { return has_jwk_claim("crv"); }
3720
3725 bool has_key_id() const noexcept { return has_jwk_claim("kid"); }
3726
3731 bool has_x5u() const noexcept { return has_jwk_claim("x5u"); }
3732
3737 bool has_x5c() const noexcept { return has_jwk_claim("x5c"); }
3738
3743 bool has_x5t() const noexcept { return has_jwk_claim("x5t"); }
3744
3749 bool has_x5t_sha256() const noexcept { return has_jwk_claim("x5t#S256"); }
3750
3755 bool has_jwk_claim(const typename json_traits::string_type& name) const noexcept {
3756 return jwk_claims.has_claim(name);
3757 }
3758
3764 basic_claim_t get_jwk_claim(const typename json_traits::string_type& name) const {
3765 return jwk_claims.get_claim(name);
3766 }
3767
3772 bool empty() const noexcept { return jwk_claims.empty(); }
3773
3778 typename json_traits::object_type get_claims() const { return this->jwk_claims.claims; }
3779 };
3780
3791 template<typename json_traits>
3792 class jwks {
3793 public:
3797 using jwks_vector_t = std::vector<jwks_t>;
3798 using iterator = typename jwks_vector_t::iterator;
3799 using const_iterator = typename jwks_vector_t::const_iterator;
3800
3804 jwks() = default;
3805
3812 JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type& str) {
3813 typename json_traits::value_type parsed_val;
3814 if (!json_traits::parse(parsed_val, str)) throw error::invalid_json_exception();
3815
3816 const details::map_of_claims<json_traits> jwks_json = json_traits::as_object(parsed_val);
3817 if (!jwks_json.has_claim("keys")) throw error::invalid_json_exception();
3818
3819 auto jwk_list = jwks_json.get_claim("keys").as_array();
3820 std::transform(jwk_list.begin(), jwk_list.end(), std::back_inserter(jwk_claims),
3821 [](const typename json_traits::value_type& val) { return jwks_t{val}; });
3822 }
3823
3824 iterator begin() { return jwk_claims.begin(); }
3825 iterator end() { return jwk_claims.end(); }
3826 const_iterator cbegin() const { return jwk_claims.begin(); }
3827 const_iterator cend() const { return jwk_claims.end(); }
3828 const_iterator begin() const { return jwk_claims.begin(); }
3829 const_iterator end() const { return jwk_claims.end(); }
3830
3835 bool has_jwk(const typename json_traits::string_type& key_id) const noexcept {
3836 return find_by_kid(key_id) != end();
3837 }
3838
3844 jwks_t get_jwk(const typename json_traits::string_type& key_id) const {
3845 const auto maybe = find_by_kid(key_id);
3846 if (maybe == end()) throw error::claim_not_present_exception();
3847 return *maybe;
3848 }
3849
3850 private:
3851 jwks_vector_t jwk_claims;
3852
3853 const_iterator find_by_kid(const typename json_traits::string_type& key_id) const noexcept {
3854 return std::find_if(cbegin(), cend(), [key_id](const jwks_t& jwk) {
3855 if (!jwk.has_key_id()) { return false; }
3856 return jwk.get_key_id() == key_id;
3857 });
3858 }
3859 };
3860
3866 template<typename Clock, typename json_traits>
3870
3876 template<typename Clock, typename json_traits>
3880
3889 date now() const { return date::clock::now(); }
3890 };
3891
3900 template<typename json_traits>
3902 return verifier<default_clock, json_traits>(c);
3903 }
3904
3908 template<typename json_traits>
3910 return builder<default_clock, json_traits>(c);
3911 }
3912
3927 template<typename json_traits, typename Decode>
3928 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token, Decode decode) {
3929 return decoded_jwt<json_traits>(token, decode);
3930 }
3931
3942 template<typename json_traits>
3943 decoded_jwt<json_traits> decode(const typename json_traits::string_type& token) {
3944 return decoded_jwt<json_traits>(token);
3945 }
3952 template<typename json_traits>
3953 jwk<json_traits> parse_jwk(const typename json_traits::string_type& jwk_) {
3954 return jwk<json_traits>(jwk_);
3955 }
3966 template<typename json_traits>
3967 jwks<json_traits> parse_jwks(const typename json_traits::string_type& jwks_) {
3968 return jwks<json_traits>(jwks_);
3969 }
3970} // namespace jwt
3971
3972template<typename json_traits>
3973std::istream& operator>>(std::istream& is, jwt::basic_claim<json_traits>& c) {
3974 return c.operator>>(is);
3975}
3976
3977template<typename json_traits>
3978std::ostream& operator<<(std::ostream& os, const jwt::basic_claim<json_traits>& c) {
3979 return os << c.to_json();
3980}
3981
3982#ifndef JWT_DISABLE_PICOJSON
3983#include "traits/kazuho-picojson/defaults.h"
3984#endif
3985
3986#endif
a class to store a generic JSON value as claim
Definition jwt.h:2307
json_traits::number_type as_number() const
Definition jwt.h:2436
set_t as_set() const
Definition jwt.h:2409
json::type get_type() const
Definition jwt.h:2374
std::set< typename json_traits::string_type > set_t
Definition jwt.h:2333
std::istream & operator>>(std::istream &is)
Definition jwt.h:2361
json_traits::boolean_type as_boolean() const
Definition jwt.h:2429
date as_date() const
Get the contained JSON value as a date.
Definition jwt.h:2391
std::ostream & operator<<(std::ostream &os)
Definition jwt.h:2367
json_traits::integer_type as_integer() const
Definition jwt.h:2422
json_traits::value_type to_json() const
Definition jwt.h:2355
json_traits::array_type as_array() const
Definition jwt.h:2402
json_traits::string_type as_string() const
Definition jwt.h:2381
Definition jwt.h:2847
builder & set_audience(typename json_traits::string_type aud)
Definition jwt.h:2965
builder & set_payload_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition jwt.h:2897
builder & set_expires_in(const std::chrono::duration< Rep > &d)
Definition jwt.h:2980
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:2908
builder & set_expires_at(const date &d)
Definition jwt.h:2973
builder & set_type(typename json_traits::string_type str)
Definition jwt.h:2916
JWT_CLAIM_EXPLICIT builder(Clock c)
Definition jwt.h:2859
json_traits::string_type sign(const Algo &algo, std::error_code &ec) const
Definition jwt.h:3083
builder & set_issued_at(const date &d)
Definition jwt.h:2994
json_traits::string_type sign(const Algo &algo) const
Definition jwt.h:3037
builder & set_payload_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition jwt.h:2887
builder & set_id(const typename json_traits::string_type &str)
Definition jwt.h:3005
builder & set_header_claim(const typename json_traits::string_type &id, typename json_traits::value_type c)
Definition jwt.h:2866
builder & set_header_claim(const typename json_traits::string_type &id, basic_claim< json_traits > c)
Definition jwt.h:2877
json_traits::string_type sign(const Algo &algo, Encode encode) const
Definition jwt.h:3021
builder & set_audience(typename json_traits::array_type a)
Definition jwt.h:2957
json_traits::string_type sign(const Algo &algo, Encode encode, std::error_code &ec) const
Definition jwt.h:3058
builder & set_content_type(typename json_traits::string_type str)
Definition jwt.h:2924
builder & set_not_before(const date &d)
Definition jwt.h:2988
builder & set_subject(typename json_traits::string_type str)
Definition jwt.h:2949
builder & set_issued_now()
Definition jwt.h:2999
builder & set_key_id(typename json_traits::string_type str)
Set key id claim.
Definition jwt.h:2933
builder & set_issuer(typename json_traits::string_type str)
Definition jwt.h:2941
Definition jwt.h:2712
const json_traits::string_type & get_header() const noexcept
Definition jwt.h:2784
const json_traits::string_type & get_signature_base64() const noexcept
Definition jwt.h:2809
json_traits::string_type signature
Signature part decoded from base64.
Definition jwt.h:2725
json_traits::string_type header
Header part decoded from base64.
Definition jwt.h:2717
json_traits::string_type header_base64
Unmodified header part in base64.
Definition jwt.h:2719
json_traits::string_type token
Unmodified token, as passed to constructor.
Definition jwt.h:2715
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2827
const json_traits::string_type & get_signature() const noexcept
Definition jwt.h:2794
JWT_CLAIM_EXPLICIT decoded_jwt(const typename json_traits::string_type &token)
Parses a given token.
Definition jwt.h:2741
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2837
decoded_jwt(const typename json_traits::string_type &token, Decode decode)
Parses a given token.
Definition jwt.h:2758
json_traits::object_type get_payload_json() const
Definition jwt.h:2814
json_traits::string_type signature_base64
Unmodified signature part in base64.
Definition jwt.h:2727
const json_traits::string_type & get_payload_base64() const noexcept
Definition jwt.h:2804
const json_traits::string_type & get_token() const noexcept
Definition jwt.h:2779
json_traits::object_type get_header_json() const
Definition jwt.h:2819
const json_traits::string_type & get_payload() const noexcept
Definition jwt.h:2789
const json_traits::string_type & get_header_base64() const noexcept
Definition jwt.h:2799
json_traits::string_type payload_base64
Unmodified payload part in base64.
Definition jwt.h:2723
json_traits::string_type payload
Payload part decoded from base64.
Definition jwt.h:2721
Definition jwt.h:2637
json_traits::string_type get_type() const
Definition jwt.h:2676
bool has_header_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:2695
bool has_algorithm() const noexcept
Definition jwt.h:2647
bool has_type() const noexcept
Definition jwt.h:2652
json_traits::string_type get_algorithm() const
Definition jwt.h:2669
bool has_content_type() const noexcept
Definition jwt.h:2657
basic_claim_t get_header_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2703
json_traits::string_type get_key_id() const
Definition jwt.h:2690
json_traits::string_type get_content_type() const
Definition jwt.h:2683
bool has_key_id() const noexcept
Definition jwt.h:2662
Handle class for EVP_PKEY structures.
Definition jwt.h:421
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:445
JSON Web Key.
Definition jwt.h:3581
bool has_x5c() const noexcept
Definition jwt.h:3737
json_traits::string_type get_curve() const
Get curve claim.
Definition jwt.h:3644
bool has_x5t_sha256() const noexcept
Definition jwt.h:3749
json_traits::string_type get_algorithm() const
Definition jwt.h:3624
json_traits::array_type get_x5c() const
Definition jwt.h:3652
json_traits::object_type get_claims() const
Definition jwt.h:3778
json_traits::string_type get_x5t() const
Definition jwt.h:3668
json_traits::string_type get_x5c_key_value() const
Definition jwt.h:3684
json_traits::string_type get_x5t_sha256() const
Definition jwt.h:3676
json_traits::string_type get_key_id() const
Definition jwt.h:3632
bool has_algorithm() const noexcept
Definition jwt.h:3713
json_traits::string_type get_use() const
Definition jwt.h:3608
bool has_key_id() const noexcept
Definition jwt.h:3725
bool has_x5u() const noexcept
Definition jwt.h:3731
bool has_key_operations() const noexcept
Definition jwt.h:3707
bool empty() const noexcept
Definition jwt.h:3772
bool has_use() const noexcept
Definition jwt.h:3701
bool has_x5t() const noexcept
Definition jwt.h:3743
bool has_jwk_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:3755
basic_claim_t::set_t get_key_operations() const
Definition jwt.h:3616
bool has_curve() const noexcept
Definition jwt.h:3719
bool has_key_type() const noexcept
Definition jwt.h:3695
basic_claim_t get_jwk_claim(const typename json_traits::string_type &name) const
Definition jwt.h:3764
json_traits::string_type get_x5u() const
Definition jwt.h:3660
json_traits::string_type get_key_type() const
Definition jwt.h:3600
JWK Set.
Definition jwt.h:3792
jwks_t get_jwk(const typename json_traits::string_type &key_id) const
Definition jwt.h:3844
jwks()=default
std::vector< jwks_t > jwks_vector_t
Type specialization for the vector of JWK.
Definition jwt.h:3797
JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type &str)
Definition jwt.h:3812
bool has_jwk(const typename json_traits::string_type &key_id) const noexcept
Definition jwt.h:3835
Definition jwt.h:2519
basic_claim_t::set_t get_audience() const
Definition jwt.h:2581
json_traits::string_type get_id() const
Definition jwt.h:2614
bool has_issued_at() const noexcept
Definition jwt.h:2555
bool has_not_before() const noexcept
Definition jwt.h:2550
bool has_payload_claim(const typename json_traits::string_type &name) const noexcept
Definition jwt.h:2619
bool has_subject() const noexcept
Definition jwt.h:2535
date get_not_before() const
Definition jwt.h:2600
bool has_issuer() const noexcept
Definition jwt.h:2530
bool has_id() const noexcept
Definition jwt.h:2560
bool has_expires_at() const noexcept
Definition jwt.h:2545
date get_issued_at() const
Definition jwt.h:2607
basic_claim_t get_payload_claim(const typename json_traits::string_type &name) const
Definition jwt.h:2627
bool has_audience() const noexcept
Definition jwt.h:2540
date get_expires_at() const
Definition jwt.h:2593
json_traits::string_type get_subject() const
Definition jwt.h:2574
json_traits::string_type get_issuer() const
Definition jwt.h:2567
Definition jwt.h:3318
verifier & expires_at_leeway(size_t leeway)
Definition jwt.h:3399
verifier & with_claim(const typename json_traits::string_type &name, verify_check_fn_t fn)
Definition jwt.h:3498
void verify(const decoded_jwt< json_traits > &jwt, std::error_code &ec) const
Definition jwt.h:3551
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:3330
verifier & not_before_leeway(size_t leeway)
Definition jwt.h:3409
verifier & issued_at_leeway(size_t leeway)
Definition jwt.h:3419
verifier & with_subject(const typename json_traits::string_type &sub)
Definition jwt.h:3455
verifier & with_audience(const typename basic_claim_t::set_t &aud)
Definition jwt.h:3464
verifier & with_claim(const typename json_traits::string_type &name, basic_claim_t c)
Definition jwt.h:3513
verifier & with_audience(const typename json_traits::string_type &aud)
Definition jwt.h:3474
void verify(const decoded_jwt< json_traits > &jwt) const
Definition jwt.h:3541
verifier(Clock c)
Definition jwt.h:3360
verifier & leeway(size_t leeway)
Definition jwt.h:3389
verifier & with_issuer(const typename json_traits::string_type &iss)
Definition jwt.h:3445
verifier & allow_algorithm(Algorithm alg)
Add an algorithm available for checking.
Definition jwt.h:3531
verifier & with_type(const typename json_traits::string_type &type, std::locale locale=std::locale{})
Definition jwt.h:3435
verifier & with_id(const typename json_traits::string_type &id)
Definition jwt.h:3485
signature_verification_error
Errors related to verification of signatures.
Definition jwt.h:212
std::error_category & token_verification_error_category()
Error category for token verification errors.
Definition jwt.h:347
void throw_if_error(std::error_code ec)
Raises an exception if any JWT-CPP error codes are active.
Definition jwt.h:379
std::error_category & ecdsa_error_category()
Error category for ECDSA errors.
Definition jwt.h:177
std::error_category & signature_verification_error_category()
Error category for verification errors.
Definition jwt.h:226
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:285
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:265
token_verification_error
Errors related to token verification errors.
Definition jwt.h:335
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:538
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:814
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:710
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:913
std::unique_ptr< BIGNUM, decltype(&BN_free)> raw2bn(const std::string &raw, std::error_code &ec)
Definition jwt.h:843
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:893
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:624
std::string bn2raw(const BIGNUM *bn)
Definition jwt.h:830
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:768
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:588
type
Categories for the various JSON types used in JWTs.
Definition jwt.h:2034
JSON Web Token.
Definition base.h:21
verifier< Clock, json_traits > verify(Clock c)
Definition jwt.h:3867
std::chrono::system_clock::time_point date
Definition jwt.h:86
builder< Clock, json_traits > create(Clock c)
Definition jwt.h:3877
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:3953
jwks< json_traits > parse_jwks(const typename json_traits::string_type &jwks_)
Definition jwt.h:3967
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:3928
verify_ops::verify_context< traits::boost_json > verify_context
Definition defaults.h:88
Base class for ECDSA family of algorithms.
Definition jwt.h:1302
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1376
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1339
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:1314
std::string name() const
Definition jwt.h:1415
Definition jwt.h:1938
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:1948
Definition jwt.h:1960
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:1970
Base class for EdDSA family of algorithms.
Definition jwt.h:1533
std::string name() const
Definition jwt.h:1647
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:1544
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1560
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1608
Definition jwt.h:1865
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:1875
Definition jwt.h:1916
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:1925
Definition jwt.h:1882
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:1892
Definition jwt.h:1899
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:1909
Base class for HMAC family of algorithms.
Definition jwt.h:1132
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1149
std::string name() const
Definition jwt.h:1189
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1170
hmacsha(std::string key, const EVP_MD *(*md)(), std::string name)
Definition jwt.h:1140
Definition jwt.h:1787
hs256(std::string key)
Definition jwt.h:1792
Definition jwt.h:1797
hs384(std::string key)
Definition jwt.h:1802
Definition jwt.h:1807
hs512(std::string key)
Definition jwt.h:1812
"none" algorithm.
Definition jwt.h:1107
void verify(const std::string &, const std::string &signature, std::error_code &ec) const
Check if the given signature is empty.
Definition jwt.h:1122
std::string name() const
Get algorithm name.
Definition jwt.h:1127
std::string sign(const std::string &, std::error_code &ec) const
Return an empty string.
Definition jwt.h:1111
Definition jwt.h:1979
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:1987
Definition jwt.h:1994
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:2002
Definition jwt.h:2009
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:2017
Base class for PSS-RSA family of algorithms.
Definition jwt.h:1659
std::string name() const
Definition jwt.h:1773
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:1669
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1734
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1686
Definition jwt.h:1819
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:1828
Definition jwt.h:1835
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:1843
Definition jwt.h:1850
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:1858
Base class for RSA family of algorithms.
Definition jwt.h:1202
void verify(const std::string &data, const std::string &signature, std::error_code &ec) const
Definition jwt.h:1263
std::string sign(const std::string &data, std::error_code &ec) const
Definition jwt.h:1229
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:1213
std::string name() const
Definition jwt.h:1289
Definition jwt.h:3884
date now() const
Definition jwt.h:3889
Definition jwt.h:101
Definition jwt.h:98
Definition jwt.h:3170
Definition jwt.h:3099
date current_time
Current time, retrieved from the verifiers clock and cached for performance and consistency.
Definition jwt.h:3103
basic_claim< json_traits > get_claim(bool in_header, json::type t, std::error_code &ec) const
Definition jwt.h:3140
size_t default_leeway
The configured default leeway for this verification.
Definition jwt.h:3107
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:3118
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:3161
basic_claim< json_traits > get_claim(std::error_code &ec) const
Helper method to get a payload claim from the jwt.
Definition jwt.h:3154
json_traits::string_type claim_key
The claim key to apply this comparison on.
Definition jwt.h:3110
const decoded_jwt< json_traits > & jwt
The jwt passed to the verifier.
Definition jwt.h:3105