mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-16 09:48:30 +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>
|
template <typename T>
|
||||||
struct is_sequence_concept<T,
|
struct is_sequence_concept<T,
|
||||||
void_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
|
>: std::true_type
|
||||||
{
|
{
|
||||||
|
@ -147,7 +152,10 @@ struct is_sequence_concept<T,
|
||||||
std::is_base_of<
|
std::is_base_of<
|
||||||
std::forward_iterator_tag,
|
std::forward_iterator_tag,
|
||||||
typename std::remove_reference_t<T>::iterator::iterator_category
|
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(
|
decltype(
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CPP_JWT_EXCEPTIONS_HPP
|
#define CPP_JWT_EXCEPTIONS_HPP
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace jwt {
|
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
|
} // END namespace jwt
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define JWT_IPP
|
#define JWT_IPP
|
||||||
|
|
||||||
#include "jwt/detail/meta.hpp"
|
#include "jwt/detail/meta.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace jwt {
|
namespace jwt {
|
||||||
|
|
||||||
|
@ -100,6 +101,9 @@ void jwt_payload::decode(const string_view enc_str, std::error_code& ec) noexcep
|
||||||
ec = DecodeErrc::JsonParseError;
|
ec = DecodeErrc::JsonParseError;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//validate the fields
|
||||||
|
//TODO:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,15 +144,12 @@ std::string jwt_signature::encode(const jwt_header& header,
|
||||||
return jwt_msg;
|
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 hdr_pld_sign,
|
||||||
const string_view jwt_sign)
|
const string_view jwt_sign)
|
||||||
{
|
{
|
||||||
//TODO: is bool the right choice ?
|
|
||||||
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
||||||
verify_fn(key_, hdr_pld_sign, jwt_sign);
|
return verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,19 +400,57 @@ jwt_object decode(const string_view enc_str,
|
||||||
set_decode_params(dparams, std::forward<Args>(args)...);
|
set_decode_params(dparams, std::forward<Args>(args)...);
|
||||||
|
|
||||||
jwt_object obj;
|
jwt_object obj;
|
||||||
|
|
||||||
auto parts = jwt_object::three_parts(enc_str);
|
auto parts = jwt_object::three_parts(enc_str);
|
||||||
|
|
||||||
//throws decode error
|
//throws decode error
|
||||||
obj.header(jwt_header{parts[0]});
|
obj.header(jwt_header{parts[0]});
|
||||||
|
|
||||||
//throws decode error
|
//throws decode error
|
||||||
obj.payload(jwt_payload{parts[1]});
|
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};
|
jwt_signature jsign{key};
|
||||||
|
|
||||||
// Length of the encoded header and payload only.
|
// Length of the encoded header and payload only.
|
||||||
// Addition of '1' to account for the '.' character.
|
// Addition of '1' to account for the '.' character.
|
||||||
auto l = parts[0].length() + 1 + parts[1].length();
|
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;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,7 @@ public: // Exposed APIs
|
||||||
{
|
{
|
||||||
// Duplicate claim names not allowed
|
// Duplicate claim names not allowed
|
||||||
// if overwrite flag is set to true.
|
// if overwrite flag is set to true.
|
||||||
|
std::cout << "Adding claim: " << claim_names_.size() << std::endl;
|
||||||
auto itr = claim_names_.find(cname);
|
auto itr = claim_names_.find(cname);
|
||||||
if (itr != claim_names_.end() && !overwrite) {
|
if (itr != claim_names_.end() && !overwrite) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -327,10 +328,49 @@ public: // Exposed APIs
|
||||||
return add_claim(
|
return add_claim(
|
||||||
cname,
|
cname,
|
||||||
std::chrono::duration_cast<
|
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)
|
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);
|
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>
|
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 hdr_pld_sign,
|
||||||
const string_view jwt_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);
|
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(const string_view name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
jwt_object& remove_claim(enum registered_claims cname)
|
||||||
|
{
|
||||||
|
return remove_claim(reg_claims_to_str(cname));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
std::string signature() const;
|
std::string signature() const;
|
||||||
|
|
Binary file not shown.
|
@ -2,6 +2,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <ctime>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "jwt/jwt.hpp"
|
#include "jwt/jwt.hpp"
|
||||||
|
|
||||||
|
@ -74,15 +75,18 @@ MIGkAgEBBDBeLCgapjZmvTatMHaYX3A02+0Ys3Tr8kda+E9DFnmCSiCOEig519fT
|
||||||
.add_claim("where", "airport")
|
.add_claim("where", "airport")
|
||||||
.add_claim("time_str", "8:18pm 24 Nov 2017")
|
.add_claim("time_str", "8:18pm 24 Nov 2017")
|
||||||
.add_claim("id", 1)
|
.add_claim("id", 1)
|
||||||
|
.add_claim("exp", std::chrono::system_clock::now())
|
||||||
;
|
;
|
||||||
|
|
||||||
std::cout << "pem sign " << obj.signature() << std::endl;
|
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"}));
|
auto dec_obj = jwt::decode(obj.signature(), pub_key, algorithms({"es256"}));
|
||||||
std::cout << dec_obj.payload() << std::endl;
|
std::cout << dec_obj.payload() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
basic_jwt_object_test();
|
//basic_jwt_object_test();
|
||||||
jwt_object_pem_test();
|
jwt_object_pem_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue