mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-15 01:08:31 +00:00
Add support for additional headers
This commit is contained in:
parent
7ddf7ec3e9
commit
161e5d8753
4 changed files with 133 additions and 48 deletions
|
@ -322,7 +322,10 @@ template <typename Map, typename... Rest>
|
||||||
void jwt_object::set_parameters(
|
void jwt_object::set_parameters(
|
||||||
params::detail::headers_param<Map>&& header, Rest&&... rargs)
|
params::detail::headers_param<Map>&& header, Rest&&... rargs)
|
||||||
{
|
{
|
||||||
//TODO: add kid support
|
for (const auto& elem : header.get()) {
|
||||||
|
header_.add_header(std::move(elem.first), std::move(elem.second));
|
||||||
|
}
|
||||||
|
|
||||||
set_parameters(std::forward<Rest>(rargs)...);
|
set_parameters(std::forward<Rest>(rargs)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,48 @@ jwt::string_view reg_claims_to_str(enum registered_claims claim) noexcept
|
||||||
assert (0 && "Code not reached");
|
assert (0 && "Code not reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class that enables reuse of the
|
||||||
|
* std::set container with custom comparator.
|
||||||
|
*/
|
||||||
|
struct jwt_set
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transparent comparator.
|
||||||
|
* @note: C++14 only.
|
||||||
|
*/
|
||||||
|
struct case_compare
|
||||||
|
{
|
||||||
|
using is_transparent = std::true_type;
|
||||||
|
|
||||||
|
bool operator()(const std::string& lhs, const std::string& rhs) const
|
||||||
|
{
|
||||||
|
int ret = strcmp(lhs.c_str(), rhs.c_str());
|
||||||
|
return (ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const jwt::string_view lhs, const jwt::string_view rhs) const
|
||||||
|
{
|
||||||
|
int ret = strcmp(lhs.data(), rhs.data());
|
||||||
|
return (ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const std::string& lhs, const jwt::string_view rhs) const
|
||||||
|
{
|
||||||
|
int ret = strcmp(lhs.data(), rhs.data());
|
||||||
|
return (ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const jwt::string_view lhs, const std::string& rhs) const
|
||||||
|
{
|
||||||
|
int ret = strcmp(lhs.data(), rhs.data());
|
||||||
|
return (ret < 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using header_claim_set_t = std::set<std::string, case_compare>;
|
||||||
|
};
|
||||||
|
|
||||||
// Fwd declaration for friend functions to specify the
|
// Fwd declaration for friend functions to specify the
|
||||||
// default arguments
|
// default arguments
|
||||||
// See: https://stackoverflow.com/a/23336823/434233
|
// See: https://stackoverflow.com/a/23336823/434233
|
||||||
|
@ -235,7 +277,11 @@ public: // 'tors
|
||||||
/*
|
/*
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
*/
|
*/
|
||||||
jwt_header() = default;
|
jwt_header()
|
||||||
|
{
|
||||||
|
payload_["alg"] = "none";
|
||||||
|
payload_["typ"] = "JWT";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor taking specified algorithm type
|
* Constructor taking specified algorithm type
|
||||||
|
@ -245,6 +291,8 @@ public: // 'tors
|
||||||
: alg_(alg)
|
: alg_(alg)
|
||||||
, typ_(typ)
|
, typ_(typ)
|
||||||
{
|
{
|
||||||
|
payload_["typ"] = type_to_str(typ_).to_string();
|
||||||
|
payload_["alg"] = alg_to_str(alg_).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,9 +317,10 @@ public: // Exposed APIs
|
||||||
/**
|
/**
|
||||||
* Set the algorithm.
|
* Set the algorithm.
|
||||||
*/
|
*/
|
||||||
void algo(enum algorithm alg) noexcept
|
void algo(enum algorithm alg)
|
||||||
{
|
{
|
||||||
alg_ = alg;
|
alg_ = alg;
|
||||||
|
payload_["alg"] = alg_to_str(alg_).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -280,6 +329,7 @@ public: // Exposed APIs
|
||||||
void algo(const jwt::string_view sv)
|
void algo(const jwt::string_view sv)
|
||||||
{
|
{
|
||||||
alg_ = str_to_alg(sv.data());
|
alg_ = str_to_alg(sv.data());
|
||||||
|
payload_["alg"] = alg_to_str(alg_).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -295,11 +345,21 @@ public: // Exposed APIs
|
||||||
* header would not be valid after modifying the type.
|
* header would not be valid after modifying the type.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Set the JWS type.
|
* Set the JWT type.
|
||||||
*/
|
*/
|
||||||
void typ(enum type typ) noexcept
|
void typ(enum type typ) noexcept
|
||||||
{
|
{
|
||||||
typ_ = typ;
|
typ_ = typ;
|
||||||
|
payload_["typ"] = type_to_str(typ_).to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the JWT type header. String overload.
|
||||||
|
*/
|
||||||
|
void typ(const jwt::string_view sv)
|
||||||
|
{
|
||||||
|
typ_ = str_to_type(sv.data());
|
||||||
|
payload_["typ"] = type_to_str(typ_).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,6 +370,38 @@ public: // Exposed APIs
|
||||||
return typ_;
|
return typ_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a header to the JWT header.
|
||||||
|
*/
|
||||||
|
template <typename T,
|
||||||
|
typename=std::enable_if_t<
|
||||||
|
!std::is_same<jwt::string_view, std::decay_t<T>>::value
|
||||||
|
>
|
||||||
|
>
|
||||||
|
bool add_header(const jwt::string_view hname, T&& hvalue, bool overwrite=false)
|
||||||
|
{
|
||||||
|
auto itr = headers_.find(hname);
|
||||||
|
if (itr != std::end(headers_) && !overwrite) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers_.emplace(hname.data(), hname.length());
|
||||||
|
payload_[hname.data()] = std::forward<T>(hvalue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a header to the JWT header.
|
||||||
|
* Overload which takes the header value as `jwt::string_view`
|
||||||
|
*/
|
||||||
|
bool add_header(const jwt::string_view cname, const jwt::string_view cvalue, bool overwrite=false)
|
||||||
|
{
|
||||||
|
return add_header(cname,
|
||||||
|
std::string{cvalue.data(), cvalue.length()},
|
||||||
|
overwrite);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the URL safe base64 encoded string
|
* Get the URL safe base64 encoded string
|
||||||
* of the header.
|
* of the header.
|
||||||
|
@ -347,14 +439,9 @@ public: // Exposed APIs
|
||||||
* @note: Presence of this member function is a requirement
|
* @note: Presence of this member function is a requirement
|
||||||
* for some interfaces (Eg: `write_interface`).
|
* for some interfaces (Eg: `write_interface`).
|
||||||
*/
|
*/
|
||||||
json_t create_json_obj() const
|
const json_t& create_json_obj() const
|
||||||
{
|
{
|
||||||
json_t obj = json_t::object();
|
return payload_;
|
||||||
//TODO: should be able to do with string_view
|
|
||||||
obj["typ"] = type_to_str(typ_).to_string();
|
|
||||||
obj["alg"] = alg_to_str(alg_).to_string();
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private: // Data members
|
private: // Data members
|
||||||
|
@ -363,6 +450,12 @@ private: // Data members
|
||||||
|
|
||||||
/// The type of header
|
/// The type of header
|
||||||
enum type typ_ = type::JWT;
|
enum type typ_ = type::JWT;
|
||||||
|
|
||||||
|
// The JSON payload object
|
||||||
|
json_t payload_;
|
||||||
|
|
||||||
|
//Extra headers for JWS
|
||||||
|
jwt_set::header_claim_set_t headers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -424,10 +517,6 @@ public: // Exposed APIs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itr != claim_names_.end() && overwrite) {
|
|
||||||
claim_names_.erase(itr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add it to the known set of claims
|
// Add it to the known set of claims
|
||||||
claim_names_.emplace(cname.data(), cname.length());
|
claim_names_.emplace(cname.data(), cname.length());
|
||||||
|
|
||||||
|
@ -650,43 +739,11 @@ public: // Exposed APIs
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* Transparent comparator.
|
|
||||||
* @note: C++14 only.
|
|
||||||
*/
|
|
||||||
struct case_compare
|
|
||||||
{
|
|
||||||
using is_transparent = std::true_type;
|
|
||||||
|
|
||||||
bool operator()(const std::string& lhs, const std::string& rhs) const
|
|
||||||
{
|
|
||||||
int ret = strcmp(lhs.c_str(), rhs.c_str());
|
|
||||||
return (ret < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const jwt::string_view lhs, const jwt::string_view rhs) const
|
|
||||||
{
|
|
||||||
int ret = strcmp(lhs.data(), rhs.data());
|
|
||||||
return (ret < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const std::string& lhs, const jwt::string_view rhs) const
|
|
||||||
{
|
|
||||||
int ret = strcmp(lhs.data(), rhs.data());
|
|
||||||
return (ret < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const jwt::string_view lhs, const std::string& rhs) const
|
|
||||||
{
|
|
||||||
int ret = strcmp(lhs.data(), rhs.data());
|
|
||||||
return (ret < 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// JSON object containing payload
|
/// JSON object containing payload
|
||||||
json_t payload_;
|
json_t payload_;
|
||||||
/// The set of claim names in the payload
|
/// The set of claim names in the payload
|
||||||
std::set<std::string, case_compare> claim_names_;
|
jwt_set::header_claim_set_t claim_names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Binary file not shown.
|
@ -259,6 +259,31 @@ TEST (EncodeTest, OverwriteClaimsTest)
|
||||||
EXPECT_TRUE (obj.payload().has_claim_with_value("x-pld1", "1data"));
|
EXPECT_TRUE (obj.payload().has_claim_with_value("x-pld1", "1data"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST (EncodeTest, HeaderParamTest)
|
||||||
|
{
|
||||||
|
using namespace jwt::params;
|
||||||
|
|
||||||
|
jwt::jwt_object obj{
|
||||||
|
headers({
|
||||||
|
{"alg", "none"},
|
||||||
|
{"typ", "jwt"},
|
||||||
|
}),
|
||||||
|
payload({
|
||||||
|
{"iss", "arun.muralidharan"},
|
||||||
|
{"sub", "nsfw"},
|
||||||
|
{"x-pld", "not my ex"}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ret = obj.header().add_header("kid", 1234567);
|
||||||
|
EXPECT_TRUE (ret);
|
||||||
|
|
||||||
|
ret = obj.header().add_header("crit", std::array<std::string, 1>{"exp"});
|
||||||
|
EXPECT_TRUE (ret);
|
||||||
|
|
||||||
|
std::cout << obj.header() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue