diff --git a/include/jwt/algorithm.hpp b/include/jwt/algorithm.hpp index 40e39f9..4c60d93 100644 --- a/include/jwt/algorithm.hpp +++ b/include/jwt/algorithm.hpp @@ -451,8 +451,6 @@ public: { std::error_code ec{}; - char* out; - unsigned int l; std::string ii{data.data(), data.length()}; EC_PKEY_uptr pkey{load_key(key, ec), ev_pkey_deletor}; diff --git a/include/jwt/exceptions.hpp b/include/jwt/exceptions.hpp index d8aaa87..534cc58 100644 --- a/include/jwt/exceptions.hpp +++ b/include/jwt/exceptions.hpp @@ -30,6 +30,19 @@ private: const char* msg_ = nullptr; }; +/** + */ +class SigningError : public std::runtime_error +{ +public: + /** + */ + SigningError(std::string msg) + : std::runtime_error(std::move(msg)) + { + } +}; + /** */ class DecodeError final: public std::runtime_error diff --git a/include/jwt/impl/jwt.ipp b/include/jwt/impl/jwt.ipp index ea2eb69..06fe926 100644 --- a/include/jwt/impl/jwt.ipp +++ b/include/jwt/impl/jwt.ipp @@ -6,6 +6,10 @@ namespace jwt { +/** + */ +static void jwt_throw_exception(const std::error_code& ec); + template std::string to_json_str(const T& obj, bool pretty) { @@ -124,9 +128,11 @@ void jwt_payload::decode(const string_view enc_str) throw(DecodeError) } std::string jwt_signature::encode(const jwt_header& header, - const jwt_payload& payload) + const jwt_payload& payload, + std::error_code& ec) { std::string jwt_msg; + ec.clear(); //TODO: Optimize allocations sign_func_t sign_fn = get_sign_algorithm_impl(header); @@ -137,7 +143,7 @@ std::string jwt_signature::encode(const jwt_header& header, std::string data = hdr_sign + '.' + pld_sign; auto res = sign_fn(key_, data); if (res.second) { - std::cout << res.second.message() << std::endl; + ec = res.second; return {}; } @@ -323,11 +329,21 @@ jwt_object& jwt_object::remove_claim(const string_view name) return *this; } +std::string jwt_object::signature(std::error_code& ec) const +{ + ec.clear(); + jwt_signature jws{secret_}; + return jws.encode(header_, payload_, ec); +} + std::string jwt_object::signature() const { - jwt_signature jws{secret_}; - - return jws.encode(header_, payload_); + std::error_code ec; + std::string res = signature(ec); + if (ec) { + throw SigningError(ec.message()); + } + return res; } template @@ -392,6 +408,22 @@ std::error_code jwt_object::verify( } } + //Check for NBF + if (has_claim(registered_claims::not_before)) + { + auto curr_time = + std::chrono::duration_cast< + std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count(); + + auto p_exp = payload() + .get_claim_value(registered_claims::not_before); + + if ((p_exp - dparams.leeway) < curr_time) { + ec = VerificationErrc::ImmatureSignature; + return ec; + } + } + return ec; } @@ -564,33 +596,34 @@ void jwt_throw_exception(const std::error_code& ec) if (&cat == &theVerificationErrorCategory) { - switch (ec.value()) { - case VerificationErrc::InvalidAlgorithm: + switch (static_cast(ec.value())) { - throw InvalidAlgorithmError(ec.message()); - } - case VerificationErrc::TokenExpired: - { - throw TokenExpiredError(ec.message()); - } - case VerificationErrc::InvalidIssuer: - { - throw InvalidIssuerError(ec.message()); - } - case VerificationErrc::InvalidAudience: - { - throw InvalidAudienceError(ec.message()); - } - case VerificationErrc::ImmatureSignature: - { - throw ImmatureSignatureError(ec.message()); - } - case VerificationErrc::InvalidSignature: - { - throw InvalidSignatureError(ec.message()); - } - default: - assert (0 && "Unknown error code"); + case VerificationErrc::InvalidAlgorithm: + { + throw InvalidAlgorithmError(ec.message()); + } + case VerificationErrc::TokenExpired: + { + throw TokenExpiredError(ec.message()); + } + case VerificationErrc::InvalidIssuer: + { + throw InvalidIssuerError(ec.message()); + } + case VerificationErrc::InvalidAudience: + { + throw InvalidAudienceError(ec.message()); + } + case VerificationErrc::ImmatureSignature: + { + throw ImmatureSignatureError(ec.message()); + } + case VerificationErrc::InvalidSignature: + { + throw InvalidSignatureError(ec.message()); + } + default: + assert (0 && "Unknown error code"); }; } @@ -601,11 +634,14 @@ void jwt_throw_exception(const std::error_code& ec) if (&cat == &theAlgorithmErrCategory) { - switch (ec.value()) { - case AlgorithmErrc::VerificationErr: - throw InvalidSignatureError(ec.message()); - default: - assert (0 && "Unknown error code or not to be treated as an error"); + switch (static_cast(ec.value())) + { + case AlgorithmErrc::VerificationErr: + { + throw InvalidSignatureError(ec.message()); + } + default: + assert (0 && "Unknown error code or not to be treated as an error"); }; } diff --git a/include/jwt/jwt.hpp b/include/jwt/jwt.hpp index 52401aa..75908a7 100644 --- a/include/jwt/jwt.hpp +++ b/include/jwt/jwt.hpp @@ -505,7 +505,8 @@ public: // Exposed APIs /*! */ std::string encode(const jwt_header& header, - const jwt_payload& payload); + const jwt_payload& payload, + std::error_code& ec); /*! */ @@ -666,6 +667,11 @@ public: // Exposed APIs /** */ + std::string signature(std::error_code& ec) const; + + /** + * Exception throwing version. + */ std::string signature() const; /** diff --git a/include/jwt/parameters.hpp b/include/jwt/parameters.hpp index 60ecf52..223e70f 100644 --- a/include/jwt/parameters.hpp +++ b/include/jwt/parameters.hpp @@ -2,6 +2,7 @@ #define CPP_JWT_PARAMETERS_HPP #include +#include #include #include #include @@ -12,6 +13,9 @@ #include "jwt/string_view.hpp" namespace jwt { + +using system_time_t = std::chrono::time_point; + namespace params { @@ -172,6 +176,24 @@ struct issuer_param std::string iss_; }; +/** + */ +struct nbf_param +{ + nbf_param(const jwt::system_time_t tp) + : duration_(std::chrono::duration_cast< + std::chrono::seconds>(tp.time_since_epoch()).count()) + {} + + nbf_param(const uint64_t epoch) + : duration_(epoch) + {} + + uint64_t get() const noexcept { return duration_; } + + uint64_t duration_; +}; + } // END namespace detail // Useful typedef @@ -289,6 +311,38 @@ algorithms(SequenceConcept&& sc) return { std::forward(sc) }; } +/** + */ +detail::audience_param +aud(const string_view aud) +{ + return { aud.data() }; +} + +/** + */ +detail::issuer_param +issuer(const string_view iss) +{ + return { iss.data() }; +} + +/** + */ +detail::nbf_param +nbf(const system_time_t tp) +{ + return { tp }; +} + +/** + */ +detail::nbf_param +nbf(const uint64_t epoch) +{ + return { epoch }; +} + } // END namespace params } // END namespace jwt diff --git a/include/jwt/test/test_jwt_object b/include/jwt/test/test_jwt_object index ffa938e..c8f68ac 100755 Binary files a/include/jwt/test/test_jwt_object and b/include/jwt/test/test_jwt_object differ