mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-16 17:58:32 +00:00
JWT veririfcation APIs
This commit is contained in:
parent
7a7353a9ef
commit
6f495c2c16
6 changed files with 152 additions and 14 deletions
|
@ -134,7 +134,12 @@ struct is_sequence_concept: std::false_type
|
|||
template <typename T>
|
||||
struct is_sequence_concept<T,
|
||||
void_t<
|
||||
std::enable_if_t<std::is_array<std::decay_t<T>>::value>
|
||||
std::enable_if_t<std::is_array<std::decay_t<T>>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view,
|
||||
std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>>::value
|
||||
>
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
|
@ -147,8 +152,11 @@ struct is_sequence_concept<T,
|
|||
std::is_base_of<
|
||||
std::forward_iterator_tag,
|
||||
typename std::remove_reference_t<T>::iterator::iterator_category
|
||||
>::value
|
||||
>,
|
||||
>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::value_type>::value
|
||||
>,
|
||||
|
||||
decltype(
|
||||
std::declval<T&>().begin(),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define CPP_JWT_EXCEPTIONS_HPP
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
|
@ -42,6 +43,18 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class VerificationError final: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
VerificationError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define JWT_IPP
|
||||
|
||||
#include "jwt/detail/meta.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
|
@ -100,6 +101,9 @@ void jwt_payload::decode(const string_view enc_str, std::error_code& ec) noexcep
|
|||
ec = DecodeErrc::JsonParseError;
|
||||
return;
|
||||
}
|
||||
|
||||
//validate the fields
|
||||
//TODO:
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -140,15 +144,12 @@ std::string jwt_signature::encode(const jwt_header& header,
|
|||
return jwt_msg;
|
||||
}
|
||||
|
||||
bool jwt_signature::verify(const jwt_header& header,
|
||||
verify_result_t jwt_signature::verify(const jwt_header& header,
|
||||
const string_view hdr_pld_sign,
|
||||
const string_view jwt_sign)
|
||||
{
|
||||
//TODO: is bool the right choice ?
|
||||
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
||||
verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||
|
||||
return true;
|
||||
return verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,19 +400,57 @@ jwt_object decode(const string_view enc_str,
|
|||
set_decode_params(dparams, std::forward<Args>(args)...);
|
||||
|
||||
jwt_object obj;
|
||||
|
||||
auto parts = jwt_object::three_parts(enc_str);
|
||||
|
||||
//throws decode error
|
||||
obj.header(jwt_header{parts[0]});
|
||||
|
||||
//throws decode error
|
||||
obj.payload(jwt_payload{parts[1]});
|
||||
|
||||
//TODO: Should be part of jwt_object::verify
|
||||
if (dparams.verify) {
|
||||
//Verify if the algorithm set in the header
|
||||
//is any of the one expected by the client.
|
||||
auto fitr = std::find_if(algos.get().begin(), algos.get().end(),
|
||||
[&](const auto& elem) {
|
||||
return jwt::str_to_alg(elem) == obj.header().algo();
|
||||
});
|
||||
|
||||
if (fitr == algos.get().end()) {
|
||||
throw VerificationError("Provided algorithms do not match with header");
|
||||
}
|
||||
|
||||
//Check for the expiry timings
|
||||
if (obj.payload().has_claim("exp")) {
|
||||
auto curr_time = std::chrono::duration_cast<
|
||||
std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
auto p_exp = obj.payload()
|
||||
.get_claim_value(registered_claims::expiration)
|
||||
.get<uint64_t>();
|
||||
|
||||
std::cout << curr_time << " :: " << p_exp << std::endl;
|
||||
|
||||
if (p_exp < curr_time) {
|
||||
throw VerificationError("Token expired");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jwt_signature jsign{key};
|
||||
|
||||
// Length of the encoded header and payload only.
|
||||
// Addition of '1' to account for the '.' character.
|
||||
auto l = parts[0].length() + 1 + parts[1].length();
|
||||
auto res = jsign.verify(obj.header(), enc_str.substr(0, l), parts[2]);
|
||||
|
||||
verify_result_t res = jsign.verify(obj.header(), enc_str.substr(0, l), parts[2]);
|
||||
if (res.second) {
|
||||
throw VerificationError(res.second.message());
|
||||
}
|
||||
|
||||
if (!res.first) {
|
||||
throw VerificationError("Verification failed due to unknown reason");
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
|
|
@ -306,6 +306,7 @@ public: // Exposed APIs
|
|||
{
|
||||
// Duplicate claim names not allowed
|
||||
// if overwrite flag is set to true.
|
||||
std::cout << "Adding claim: " << claim_names_.size() << std::endl;
|
||||
auto itr = claim_names_.find(cname);
|
||||
if (itr != claim_names_.end() && !overwrite) {
|
||||
return false;
|
||||
|
@ -327,10 +328,49 @@ public: // Exposed APIs
|
|||
return add_claim(
|
||||
cname,
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count()
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count(),
|
||||
overwrite
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename T>
|
||||
bool add_claim(enum registered_claims cname, T&& cvalue, bool overwrite=false)
|
||||
{
|
||||
return add_claim(
|
||||
reg_claims_to_str(cname),
|
||||
std::forward<T>(cvalue),
|
||||
overwrite
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
bool add_claim(enum registered_claims cname, system_time_t tp, bool overwrite=false)
|
||||
{
|
||||
return add_claim(
|
||||
reg_claims_to_str(cname),
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count(),
|
||||
overwrite
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
decltype(auto) get_claim_value(const string_view cname) const
|
||||
{
|
||||
return payload_[cname.data()];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
decltype(auto) get_claim_value(enum registered_claims cname) const
|
||||
{
|
||||
return get_claim_value(reg_claims_to_str(cname));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
bool remove_claim(const string_view cname)
|
||||
|
@ -346,11 +386,30 @@ public: // Exposed APIs
|
|||
|
||||
/**
|
||||
*/
|
||||
bool has_claim(const std::string& cname) const noexcept
|
||||
bool remove_claim(enum registered_claims cname)
|
||||
{
|
||||
return remove_claim(reg_claims_to_str(cname));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
//TODO: Not all libc++ version agrees with this
|
||||
//because count() is not made const for is_transparent
|
||||
//based overload
|
||||
bool has_claim(const string_view cname) const noexcept
|
||||
{
|
||||
std::cout << "CSZ: " << claim_names_.size() << std::endl;
|
||||
for (auto c : claim_names_) std::cout << "Claim: " << c << std::endl;
|
||||
return claim_names_.count(cname);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
bool has_claim(enum registered_claims cname) const noexcept
|
||||
{
|
||||
return has_claim(reg_claims_to_str(cname));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename T>
|
||||
|
@ -451,7 +510,7 @@ public: // Exposed APIs
|
|||
|
||||
/*!
|
||||
*/
|
||||
bool verify(const jwt_header& header,
|
||||
verify_result_t verify(const jwt_header& header,
|
||||
const string_view hdr_pld_sign,
|
||||
const string_view jwt_sign);
|
||||
|
||||
|
@ -573,10 +632,25 @@ public: // Exposed APIs
|
|||
*/
|
||||
jwt_object& add_claim(const string_view name, system_time_t time_point);
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename T>
|
||||
jwt_object& add_claim(enum registered_claims cname, T&& value)
|
||||
{
|
||||
return add_claim(reg_claims_to_str(cname), std::forward<T>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
jwt_object& remove_claim(const string_view name);
|
||||
|
||||
/**
|
||||
*/
|
||||
jwt_object& remove_claim(enum registered_claims cname)
|
||||
{
|
||||
return remove_claim(reg_claims_to_str(cname));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
std::string signature() const;
|
||||
|
|
Binary file not shown.
|
@ -2,6 +2,7 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <unordered_map>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
|
@ -74,15 +75,18 @@ MIGkAgEBBDBeLCgapjZmvTatMHaYX3A02+0Ys3Tr8kda+E9DFnmCSiCOEig519fT
|
|||
.add_claim("where", "airport")
|
||||
.add_claim("time_str", "8:18pm 24 Nov 2017")
|
||||
.add_claim("id", 1)
|
||||
.add_claim("exp", std::chrono::system_clock::now())
|
||||
;
|
||||
|
||||
std::cout << "pem sign " << obj.signature() << std::endl;
|
||||
std::cout << "Get claim value for exp: " << obj.payload().get_claim_value("exp") << std::endl;
|
||||
sleep(4);
|
||||
auto dec_obj = jwt::decode(obj.signature(), pub_key, algorithms({"es256"}));
|
||||
std::cout << dec_obj.payload() << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_jwt_object_test();
|
||||
//basic_jwt_object_test();
|
||||
jwt_object_pem_test();
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue