Code cleanup around jwt_object creation in decode step

This commit is contained in:
Arun M 2017-11-21 16:16:03 +05:30
parent cb925fee3a
commit ffd6280026
3 changed files with 165 additions and 30 deletions

View file

@ -211,6 +211,9 @@ template <typename Map, typename... Rest>
void jwt_object::set_parameters(
params::detail::payload_param<Map>&& payload, Rest&&... rargs)
{
for (const auto& elem : payload.get()) {
payload_.add_claim(std::move(elem.first), std::move(elem.second));
}
set_parameters(std::forward<Rest>(rargs)...);
}
@ -218,6 +221,7 @@ template <typename... Rest>
void jwt_object::set_parameters(
params::detail::secret_param secret, Rest&&... rargs)
{
secret_.assign(secret.get().data(), secret.get().length());
set_parameters(std::forward<Rest>(rargs)...);
}
@ -225,6 +229,7 @@ template <typename Map, typename... Rest>
void jwt_object::set_parameters(
params::detail::headers_param<Map>&& header, Rest&&... rargs)
{
//TODO: add kid support
set_parameters(std::forward<Rest>(rargs)...);
}
@ -235,37 +240,72 @@ void jwt_object::set_parameters()
}
template <typename T>
jwt_payload& jwt_object::add_payload(const std::string& name, T&& value)
jwt_payload& jwt_object::add_claim(const std::string& name, T&& value)
{
payload_.add_claim(name, std::forward<T>(value));
return payload_;
}
//====================================================================
void jwt_decode(const string_view encoded_str, const string_view key, bool validate)
jwt_payload& jwt_object::remove_claim(const std::string& name)
{
//TODO: implement error_code
size_t fpos = encoded_str.find_first_of('.');
payload_.remove_claim(name);
return payload_;
}
std::string jwt_object::signature() const
{
jwt_signature jws{secret_};
return jws.encode(header_, payload_);
}
std::array<string_view, 3>
jwt_object::three_parts(const string_view enc_str)
{
std::array<string_view, 3> result;
size_t fpos = enc_str.find_first_of('.');
assert (fpos != string_view::npos);
string_view head{&encoded_str[0], fpos};
jwt_header hdr;
hdr.decode(head);
result[0] = string_view{&enc_str[0], fpos};
size_t spos = encoded_str.find_first_of('.', fpos + 1);
size_t spos = enc_str.find_first_of('.', fpos + 1);
if (spos == string_view::npos) {
//TODO: Check for none algorithm
}
string_view body{&encoded_str[fpos + 1], spos - fpos - 1};
//Json objects or claims get set in the decode
jwt_payload pld;
pld.decode(body);
result[1] = string_view{&enc_str[fpos + 1], spos - fpos - 1};
size_t tpos = enc_str.find_first_of('.', spos + 1);
if (tpos != string_view::npos) {
result[2] = string_view{&enc_str[tpos + 1], tpos - spos - 1};
}
return result;
}
//====================================================================
jwt_object jwt_decode(const string_view encoded_str, const string_view key, bool validate)
{
//TODO: implement error_code
jwt_object jobj;
auto parts = jwt_object::three_parts(encoded_str);
jobj.header(jwt_header{parts[0]});
jobj.payload(jwt_payload{parts[1]});
jwt_signature jsign{key};
jsign.verify(hdr, encoded_str.substr(0, spos), encoded_str);
//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();
jsign.verify(jobj.header(), encoded_str.substr(0, l), encoded_str);
return jobj;
}
} // END namespace jwt

View file

@ -1,11 +1,12 @@
#ifndef JWT_HPP
#define JWT_HPP
#include <cassert>
#include <cstring>
#include <set>
#include <array>
#include <string>
#include <ostream>
#include <cassert>
#include <cstring>
#include "jwt/base64.hpp"
#include "jwt/algorithm.hpp"
@ -233,6 +234,15 @@ public: // 'tors
{
}
/**
* Construct the header from an encoded string.
* TODO: Throw an exception in case of error
*/
jwt_header(const string_view enc_str)
{
this->decode(enc_str);
}
/// Default Copy and assignment
jwt_header(const jwt_header&) = default;
jwt_header& operator=(const jwt_header&) = default;
@ -312,10 +322,19 @@ struct jwt_payload: write_interface
, base64_enc_dec<jwt_payload>
{
public: // 'tors
/*!
/**
*/
jwt_payload() = default;
/**
* Construct the payload from an encoded string.
* TODO: Throw an exception in case of error.
*/
jwt_payload(const string_view enc_str)
{
this->decode(enc_str);
}
/// Default copy and assignment operations
jwt_payload(const jwt_payload&) = default;
jwt_payload& operator=(const jwt_payload&) = default;
@ -323,7 +342,7 @@ public: // 'tors
~jwt_payload() = default;
public: // Exposed APIs
/*!
/**
*/
template <typename T>
bool add_claim(const std::string& cname, T&& cvalue, bool overwrite=false)
@ -346,14 +365,27 @@ public: // Exposed APIs
return true;
}
/*!
/**
*/
bool remove_claim(const std::string& cname)
{
auto itr = claim_names_.find(cname);
if (itr == claim_names_.end()) return false;
claim_names_.erase(itr);
payload_.erase(cname.c_str());
return true;
}
/**
*/
bool has_claim(const std::string& cname) const noexcept
{
return claim_names_.count(cname);
}
/*!
/**
*/
template <typename T>
bool has_claim_with_value(const std::string& cname, T&& cvalue) const
@ -364,19 +396,19 @@ public: // Exposed APIs
return (cvalue == payload_[cname]);
}
/*!
/**
*/
std::string encode(bool pprint = false)
{
return base64_encode(pprint);
}
/*!
/**
*/
//TODO: what about error_code ?
void decode(const string_view enc_str);
/*!
/**
*/
const json_t& create_json_obj() const
{
@ -384,14 +416,35 @@ public: // Exposed APIs
}
private:
/*!
/**
*/
struct case_compare {
struct case_compare
{
using is_transparent = std::true_type;
bool operator()(const std::string& lhs, const std::string& rhs) const
{
int ret = strcasecmp(lhs.c_str(), rhs.c_str());
return (ret < 0);
}
bool operator()(const string_view lhs, const string_view rhs) const
{
int ret = strcasecmp(lhs.data(), rhs.data());
return (ret < 0);
}
bool operator()(const std::string& lhs, const string_view rhs) const
{
int ret = strcasecmp(lhs.data(), rhs.data());
return (ret < 0);
}
bool operator()(const string_view lhs, const std::string& rhs) const
{
int ret = strcasecmp(lhs.data(), rhs.data());
return (ret < 0);
}
};
/// JSON object containing payload
@ -449,7 +502,7 @@ private: // Data members;
};
/*!
/**
*/
class jwt_object
{
@ -463,6 +516,12 @@ public: // 'tors
template <typename... Args>
jwt_object(Args&&... args);
public: // Exposed static APIs
/**
*/
static std::array<string_view, 3>
three_parts(const string_view enc_str);
public: // Exposed APIs
/**
*/
@ -478,6 +537,34 @@ public: // Exposed APIs
return payload_;
}
/**
*/
void payload(const jwt_payload& p)
{
payload_ = p;
}
/**
*/
void payload(jwt_payload&& p)
{
payload_ = std::move(p);
}
/**
*/
void header(const jwt_header& h)
{
header_ = h;
}
/**
*/
void header(jwt_header&& h)
{
header_ = std::move(h);
}
/**
*/
jwt_header& header() noexcept
@ -495,7 +582,15 @@ public: // Exposed APIs
/**
*/
template <typename T>
jwt_payload& add_payload(const std::string& name, T&& value);
jwt_payload& add_claim(const std::string& name, T&& value);
/**
*/
jwt_payload& remove_claim(const std::string& name);
/**
*/
std::string signature() const;
private: // private APIs
/**
@ -536,7 +631,7 @@ private: // Data Members
/*!
*/
void jwt_decode(const string_view encoded_str, const string_view key, bool validate=true);
jwt_object jwt_decode(const string_view encoded_str, const string_view key, bool validate=true);
} // END namespace jwt

Binary file not shown.