Added nbf check and more exception and error code handling

This commit is contained in:
Arun M 2017-12-20 18:07:08 +05:30
parent 77c11e8eb9
commit b5088a6d9c
6 changed files with 146 additions and 39 deletions

View file

@ -451,8 +451,6 @@ public:
{ {
std::error_code ec{}; std::error_code ec{};
char* out;
unsigned int l;
std::string ii{data.data(), data.length()}; std::string ii{data.data(), data.length()};
EC_PKEY_uptr pkey{load_key(key, ec), ev_pkey_deletor}; EC_PKEY_uptr pkey{load_key(key, ec), ev_pkey_deletor};

View file

@ -30,6 +30,19 @@ private:
const char* msg_ = nullptr; 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 class DecodeError final: public std::runtime_error

View file

@ -6,6 +6,10 @@
namespace jwt { namespace jwt {
/**
*/
static void jwt_throw_exception(const std::error_code& ec);
template <typename T, typename Cond> template <typename T, typename Cond>
std::string to_json_str(const T& obj, bool pretty) 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, 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; std::string jwt_msg;
ec.clear();
//TODO: Optimize allocations //TODO: Optimize allocations
sign_func_t sign_fn = get_sign_algorithm_impl(header); 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; std::string data = hdr_sign + '.' + pld_sign;
auto res = sign_fn(key_, data); auto res = sign_fn(key_, data);
if (res.second) { if (res.second) {
std::cout << res.second.message() << std::endl; ec = res.second;
return {}; return {};
} }
@ -323,11 +329,21 @@ jwt_object& jwt_object::remove_claim(const string_view name)
return *this; 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 std::string jwt_object::signature() const
{ {
jwt_signature jws{secret_}; std::error_code ec;
std::string res = signature(ec);
return jws.encode(header_, payload_); if (ec) {
throw SigningError(ec.message());
}
return res;
} }
template <typename Params, typename SequenceT> template <typename Params, typename SequenceT>
@ -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<uint64_t>(registered_claims::not_before);
if ((p_exp - dparams.leeway) < curr_time) {
ec = VerificationErrc::ImmatureSignature;
return ec;
}
}
return ec; return ec;
} }
@ -564,33 +596,34 @@ void jwt_throw_exception(const std::error_code& ec)
if (&cat == &theVerificationErrorCategory) if (&cat == &theVerificationErrorCategory)
{ {
switch (ec.value()) { switch (static_cast<VerificationErrc>(ec.value()))
case VerificationErrc::InvalidAlgorithm:
{ {
throw InvalidAlgorithmError(ec.message()); case VerificationErrc::InvalidAlgorithm:
} {
case VerificationErrc::TokenExpired: throw InvalidAlgorithmError(ec.message());
{ }
throw TokenExpiredError(ec.message()); case VerificationErrc::TokenExpired:
} {
case VerificationErrc::InvalidIssuer: throw TokenExpiredError(ec.message());
{ }
throw InvalidIssuerError(ec.message()); case VerificationErrc::InvalidIssuer:
} {
case VerificationErrc::InvalidAudience: throw InvalidIssuerError(ec.message());
{ }
throw InvalidAudienceError(ec.message()); case VerificationErrc::InvalidAudience:
} {
case VerificationErrc::ImmatureSignature: throw InvalidAudienceError(ec.message());
{ }
throw ImmatureSignatureError(ec.message()); case VerificationErrc::ImmatureSignature:
} {
case VerificationErrc::InvalidSignature: throw ImmatureSignatureError(ec.message());
{ }
throw InvalidSignatureError(ec.message()); case VerificationErrc::InvalidSignature:
} {
default: throw InvalidSignatureError(ec.message());
assert (0 && "Unknown error code"); }
default:
assert (0 && "Unknown error code");
}; };
} }
@ -601,11 +634,14 @@ void jwt_throw_exception(const std::error_code& ec)
if (&cat == &theAlgorithmErrCategory) if (&cat == &theAlgorithmErrCategory)
{ {
switch (ec.value()) { switch (static_cast<AlgorithmErrc>(ec.value()))
case AlgorithmErrc::VerificationErr: {
throw InvalidSignatureError(ec.message()); case AlgorithmErrc::VerificationErr:
default: {
assert (0 && "Unknown error code or not to be treated as an error"); throw InvalidSignatureError(ec.message());
}
default:
assert (0 && "Unknown error code or not to be treated as an error");
}; };
} }

View file

@ -505,7 +505,8 @@ public: // Exposed APIs
/*! /*!
*/ */
std::string encode(const jwt_header& header, 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; std::string signature() const;
/** /**

View file

@ -2,6 +2,7 @@
#define CPP_JWT_PARAMETERS_HPP #define CPP_JWT_PARAMETERS_HPP
#include <map> #include <map>
#include <chrono>
#include <string> #include <string>
#include <vector> #include <vector>
#include <utility> #include <utility>
@ -12,6 +13,9 @@
#include "jwt/string_view.hpp" #include "jwt/string_view.hpp"
namespace jwt { namespace jwt {
using system_time_t = std::chrono::time_point<std::chrono::system_clock>;
namespace params { namespace params {
@ -172,6 +176,24 @@ struct issuer_param
std::string iss_; 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 } // END namespace detail
// Useful typedef // Useful typedef
@ -289,6 +311,38 @@ algorithms(SequenceConcept&& sc)
return { std::forward<SequenceConcept>(sc) }; return { std::forward<SequenceConcept>(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 params
} // END namespace jwt } // END namespace jwt

Binary file not shown.