Added decode error codes and exceptions

This commit is contained in:
Arun M 2017-12-04 13:17:48 +05:30
parent 234411a550
commit 9e69389caf
7 changed files with 131 additions and 18 deletions

View file

@ -282,7 +282,8 @@ std::string base64_uri_decode(const char* data, size_t len)
size_t i = 0; size_t i = 0;
for (; i < len; ++i) { for (; i < len; ++i)
{
switch (data[i]) { switch (data[i]) {
case '-': case '-':
uri_dec[i] = '+'; uri_dec[i] = '+';

View file

@ -21,11 +21,25 @@ enum class AlgorithmFailureSource
{ {
}; };
/**
* Decode error conditions
*/
enum class DecodeErrc
{
JsonParseError = 1,
AlgHeaderMiss,
TypHeaderMiss,
TypMismatch,
};
/** /**
*/ */
std::error_code make_error_code(AlgorithmErrc err); std::error_code make_error_code(AlgorithmErrc err);
/**
*/
std::error_code make_error_code(DecodeErrc err);
} // END namespace jwt } // END namespace jwt
@ -37,6 +51,9 @@ namespace std
{ {
template <> template <>
struct is_error_code_enum<jwt::AlgorithmErrc> : true_type {}; struct is_error_code_enum<jwt::AlgorithmErrc> : true_type {};
template <>
struct is_error_code_enum<jwt::DecodeErrc>: true_type {};
} }
#include "jwt/impl/error_codes.ipp" #include "jwt/impl/error_codes.ipp"

View file

@ -29,6 +29,19 @@ private:
const char* msg_ = nullptr; const char* msg_ = nullptr;
}; };
/**
*/
class DecodeError final: public std::runtime_error
{
public:
/**
*/
DecodeError(std::string msg)
: std::runtime_error(std::move(msg))
{
}
};
} // END namespace jwt } // END namespace jwt

View file

@ -30,9 +30,38 @@ struct AlgorithmErrCategory: std::error_category
} }
}; };
/**
*/
struct DecodeErrorCategory: std::error_category
{
const char* name() const noexcept override
{
return "decode";
}
std::string message(int ev) const override
{
switch (static_cast<DecodeErrc>(ev))
{
case DecodeErrc::AlgHeaderMiss:
return "missing algorithm header";
case DecodeErrc::TypHeaderMiss:
return "missing type header";
case DecodeErrc::TypMismatch:
return "type mismatch";
case DecodeErrc::JsonParseError:
return "json parse failed";
};
assert (0 && "Code not reached");
}
};
// Create global object for the error categories // Create global object for the error categories
const AlgorithmErrCategory theAlgorithmErrCategory {}; const AlgorithmErrCategory theAlgorithmErrCategory {};
const DecodeErrorCategory theDecodeErrorCategory {};
} }
@ -42,6 +71,11 @@ std::error_code make_error_code(AlgorithmErrc err)
return { static_cast<int>(err), theAlgorithmErrCategory }; return { static_cast<int>(err), theAlgorithmErrCategory };
} }
std::error_code make_error_code(DecodeErrc err)
{
return { static_cast<int>(err), theDecodeErrorCategory };
}
} // END namespace jwt } // END namespace jwt

View file

@ -36,40 +36,80 @@ std::ostream& operator<< (std::ostream& os, const T& obj)
//======================================================================== //========================================================================
void jwt_header::decode(const string_view enc_str) void jwt_header::decode(const string_view enc_str, std::error_code& ec) noexcept
{ {
ec.clear();
std::string json_str = base64_decode(enc_str); std::string json_str = base64_decode(enc_str);
json_t obj = json_t::parse(std::move(json_str)); json_t obj;
try {
obj = json_t::parse(std::move(json_str));
} catch(const std::exception& e) {
ec = DecodeErrc::JsonParseError;
return;
}
//Look for the algorithm field //Look for the algorithm field
auto alg_itr = obj.find("alg"); auto alg_itr = obj.find("alg");
assert (alg_itr != obj.end() && "Algorithm header is missing"); if (alg_itr == obj.end()) {
std::error_code ec; ec = DecodeErrc::AlgHeaderMiss;
return;
}
alg_ = str_to_alg(alg_itr.value().get<std::string>()); alg_ = str_to_alg(alg_itr.value().get<std::string>());
if (alg_ != algorithm::NONE) { if (alg_ != algorithm::NONE)
{
auto itr = obj.find("typ"); auto itr = obj.find("typ");
if (itr == obj.end()) { if (itr == obj.end()) {
//TODO: set error code ec = DecodeErrc::TypHeaderMiss;
return; return;
} }
auto typ = itr.value().get<std::string>();
const auto& typ = itr.value().get<std::string>();
if (strcasecmp(typ.c_str(), "JWT")) { if (strcasecmp(typ.c_str(), "JWT")) {
//TODO: set error code ec = DecodeErrc::TypMismatch;
return; return;
} }
typ_ = str_to_type(typ); typ_ = str_to_type(typ);
} else {
//TODO:
} }
return; return;
} }
void jwt_header::decode(const string_view enc_str) throw(DecodeError)
void jwt_payload::decode(const string_view enc_str)
{ {
std::error_code ec;
decode(enc_str, ec);
if (ec) {
throw DecodeError(ec.message());
}
return;
}
void jwt_payload::decode(const string_view enc_str, std::error_code& ec) noexcept
{
ec.clear();
std::string json_str = base64_decode(enc_str); std::string json_str = base64_decode(enc_str);
try {
payload_ = json_t::parse(std::move(json_str)); payload_ = json_t::parse(std::move(json_str));
} catch(const std::exception& e) {
ec = DecodeErrc::JsonParseError;
return;
}
return;
}
void jwt_payload::decode(const string_view enc_str) throw(DecodeError)
{
std::error_code ec;
decode(enc_str, ec);
if (ec) {
throw DecodeError(ec.message());
}
return; return;
} }
@ -306,9 +346,9 @@ jwt_object jwt_decode(const string_view encoded_str, const string_view key, bool
auto parts = jwt_object::three_parts(encoded_str); auto parts = jwt_object::three_parts(encoded_str);
//throws verification error //throws decode error
jobj.header(jwt_header{parts[0]}); jobj.header(jwt_header{parts[0]});
//throws verification error //throws decode error
jobj.payload(jwt_payload{parts[1]}); jobj.payload(jwt_payload{parts[1]});
jwt_signature jsign{key}; jwt_signature jsign{key};

View file

@ -12,6 +12,7 @@
#include "jwt/algorithm.hpp" #include "jwt/algorithm.hpp"
#include "jwt/string_view.hpp" #include "jwt/string_view.hpp"
#include "jwt/parameters.hpp" #include "jwt/parameters.hpp"
#include "jwt/exceptions.hpp"
#include "jwt/json/json.hpp" #include "jwt/json/json.hpp"
// For convenience // For convenience
@ -237,9 +238,13 @@ public: // Exposed APIs
return base64_encode(pprint); return base64_encode(pprint);
} }
/*! /**
*/ */
void decode(const string_view enc_str); void decode(const string_view enc_str, std::error_code& ec) noexcept;
/**
*/
void decode(const string_view enc_str) throw(DecodeError);
/*! /*!
*/ */
@ -350,8 +355,11 @@ public: // Exposed APIs
/** /**
*/ */
//TODO: what about error_code ? void decode(const string_view enc_str, std::error_code& ec) noexcept;
void decode(const string_view enc_str);
/**
*/
void decode(const string_view enc_str) throw(DecodeError);
/** /**
*/ */

Binary file not shown.