mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-15 22:57:12 +02:00
Major plugin refactor and cleanup.
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
This commit is contained in:
35
vendor/POCO/JWT/src/JWTException.cpp
vendored
Normal file
35
vendor/POCO/JWT/src/JWTException.cpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// JWTException.cpp
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: JWTException
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/JWT/JWTException.h"
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
using Poco::Exception;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(JWTException, Exception, "JWT Exception")
|
||||
POCO_IMPLEMENT_EXCEPTION(ParseException, JWTException, "JWT parsing failed")
|
||||
POCO_IMPLEMENT_EXCEPTION(UnsupportedAlgorithmException, JWTException, "Unsupported signing algorithm")
|
||||
POCO_IMPLEMENT_EXCEPTION(UnallowedAlgorithmException, JWTException, "Unallowed signing algorithm")
|
||||
POCO_IMPLEMENT_EXCEPTION(SignatureException, JWTException, "JWT Signature Exception")
|
||||
POCO_IMPLEMENT_EXCEPTION(SignatureVerificationException, SignatureException, "JWT signature verification failed")
|
||||
POCO_IMPLEMENT_EXCEPTION(SignatureGenerationException, SignatureException, "JWT signature generation failed")
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
81
vendor/POCO/JWT/src/Serializer.cpp
vendored
Normal file
81
vendor/POCO/JWT/src/Serializer.cpp
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Serializer.cpp
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Serializer
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/JWT/Serializer.h"
|
||||
#include "Poco/JWT/JWTException.h"
|
||||
#include "Poco/JSON/Parser.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/MemoryStream.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
std::string Serializer::serialize(const Poco::JSON::Object& object)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
serialize(object, stream);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
void Serializer::serialize(const Poco::JSON::Object& object, std::ostream& stream)
|
||||
{
|
||||
Poco::Base64Encoder encoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
|
||||
object.stringify(encoder);
|
||||
encoder.close();
|
||||
}
|
||||
|
||||
|
||||
Poco::JSON::Object::Ptr Serializer::deserialize(const std::string& serialized)
|
||||
{
|
||||
Poco::MemoryInputStream stream(serialized.data(), serialized.size());
|
||||
return deserialize(stream);
|
||||
}
|
||||
|
||||
|
||||
Poco::JSON::Object::Ptr Serializer::deserialize(std::istream& stream)
|
||||
{
|
||||
Poco::Base64Decoder decoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
|
||||
Poco::JSON::Parser parser;
|
||||
try
|
||||
{
|
||||
Poco::Dynamic::Var json = parser.parse(decoder);
|
||||
Poco::JSON::Object::Ptr pObject = json.extract<Poco::JSON::Object::Ptr>();
|
||||
return pObject;
|
||||
}
|
||||
catch (Poco::BadCastException&)
|
||||
{
|
||||
throw ParseException("String does not deserialize to a JSON object");
|
||||
}
|
||||
catch (Poco::Exception& exc)
|
||||
{
|
||||
throw ParseException("Failed to deserialize JWT component", exc.displayText());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> Serializer::split(const std::string& token)
|
||||
{
|
||||
Poco::StringTokenizer tokenizer(token, ".");
|
||||
std::vector<std::string> result(tokenizer.begin(), tokenizer.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
505
vendor/POCO/JWT/src/Signer.cpp
vendored
Normal file
505
vendor/POCO/JWT/src/Signer.cpp
vendored
Normal file
@ -0,0 +1,505 @@
|
||||
//
|
||||
// Signer.cpp
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Signer
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/JWT/Signer.h"
|
||||
#include "Poco/JWT/Serializer.h"
|
||||
#include "Poco/JWT/JWTException.h"
|
||||
#include "Poco/HMACEngine.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/DynamicFactory.h"
|
||||
#include "Poco/MemoryStream.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/Crypto/DigestEngine.h"
|
||||
#include "Poco/Crypto/RSADigestEngine.h"
|
||||
#include "Poco/Crypto/ECDSADigestEngine.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
//
|
||||
// Algorithm
|
||||
//
|
||||
|
||||
|
||||
class Algorithm: public Poco::RefCountedObject
|
||||
/// Abstraction of an algorithm for signing JWTs.
|
||||
{
|
||||
public:
|
||||
typedef Poco::AutoPtr<Algorithm> Ptr;
|
||||
|
||||
Algorithm();
|
||||
/// Creates the Algorithm.
|
||||
|
||||
virtual ~Algorithm();
|
||||
/// Destroys the Algorithm.
|
||||
|
||||
virtual Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload) = 0;
|
||||
/// Signs the header and payload and returns the signature.
|
||||
|
||||
virtual bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature) = 0;
|
||||
/// Verifies the header and payload against the signature.
|
||||
///
|
||||
/// Returns true if the signature is correct, otherwise false.
|
||||
|
||||
static const std::string SHA256;
|
||||
static const std::string SHA384;
|
||||
static const std::string SHA512;
|
||||
};
|
||||
|
||||
|
||||
Algorithm::Algorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Algorithm::~Algorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const std::string Algorithm::SHA256("SHA256");
|
||||
const std::string Algorithm::SHA384("SHA384");
|
||||
const std::string Algorithm::SHA512("SHA512");
|
||||
|
||||
|
||||
class SHA256Engine: public Poco::Crypto::DigestEngine
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BLOCK_SIZE = 64,
|
||||
DIGEST_SIZE = 32
|
||||
};
|
||||
|
||||
SHA256Engine():
|
||||
Poco::Crypto::DigestEngine(Algorithm::SHA256)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SHA384Engine: public Poco::Crypto::DigestEngine
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BLOCK_SIZE = 128,
|
||||
DIGEST_SIZE = 48
|
||||
};
|
||||
|
||||
SHA384Engine():
|
||||
Poco::Crypto::DigestEngine(Algorithm::SHA384)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SHA512Engine: public Poco::Crypto::DigestEngine
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BLOCK_SIZE = 128,
|
||||
DIGEST_SIZE = 64
|
||||
};
|
||||
|
||||
SHA512Engine():
|
||||
Poco::Crypto::DigestEngine(Algorithm::SHA512)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Engine>
|
||||
class HMACAlgorithm: public Algorithm
|
||||
{
|
||||
public:
|
||||
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
|
||||
{
|
||||
if (signer.getHMACKey().empty()) throw SignatureGenerationException("No HMAC key available");
|
||||
|
||||
Poco::HMACEngine<Engine> hmac(signer.getHMACKey());
|
||||
hmac.update(header);
|
||||
hmac.update('.');
|
||||
hmac.update(payload);
|
||||
return hmac.digest();
|
||||
}
|
||||
|
||||
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
|
||||
{
|
||||
return sign(signer, header, payload) == signature;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef HMACAlgorithm<SHA256Engine> HS256;
|
||||
typedef HMACAlgorithm<SHA384Engine> HS384;
|
||||
typedef HMACAlgorithm<SHA512Engine> HS512;
|
||||
|
||||
|
||||
class RSAAlgorithm: public Algorithm
|
||||
{
|
||||
public:
|
||||
RSAAlgorithm(const std::string& digestType):
|
||||
_digestType(digestType)
|
||||
{
|
||||
}
|
||||
|
||||
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
|
||||
{
|
||||
if (!signer.getRSAKey()) throw SignatureGenerationException("No RSA key available");
|
||||
|
||||
Poco::Crypto::RSADigestEngine rsa(*signer.getRSAKey(), _digestType);
|
||||
rsa.update(header);
|
||||
rsa.update('.');
|
||||
rsa.update(payload);
|
||||
return rsa.signature();
|
||||
|
||||
}
|
||||
|
||||
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
|
||||
{
|
||||
if (!signer.getRSAKey()) throw SignatureVerificationException("No RSA key available");
|
||||
|
||||
Poco::Crypto::RSADigestEngine rsa(*signer.getRSAKey(), _digestType);
|
||||
rsa.update(header);
|
||||
rsa.update('.');
|
||||
rsa.update(payload);
|
||||
return rsa.verify(signature);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _digestType;
|
||||
};
|
||||
|
||||
|
||||
class RS256: public RSAAlgorithm
|
||||
{
|
||||
public:
|
||||
RS256():
|
||||
RSAAlgorithm(Algorithm::SHA256)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RS384: public RSAAlgorithm
|
||||
{
|
||||
public:
|
||||
RS384():
|
||||
RSAAlgorithm(Algorithm::SHA384)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RS512: public RSAAlgorithm
|
||||
{
|
||||
public:
|
||||
RS512():
|
||||
RSAAlgorithm(Algorithm::SHA512)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ECDSAAlgorithm: public Algorithm
|
||||
{
|
||||
public:
|
||||
ECDSAAlgorithm(const std::string& digestType):
|
||||
_digestType(digestType)
|
||||
{
|
||||
}
|
||||
|
||||
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
|
||||
{
|
||||
if (!signer.getECKey()) throw SignatureGenerationException("No EC key available");
|
||||
|
||||
Poco::Crypto::ECDSADigestEngine ecdsa(*signer.getECKey(), _digestType);
|
||||
ecdsa.update(header);
|
||||
ecdsa.update('.');
|
||||
ecdsa.update(payload);
|
||||
|
||||
Poco::Crypto::ECDSASignature ecdsaSig(ecdsa.signature());
|
||||
Poco::DigestEngine::Digest jwtSig(ecdsaSig.rawR());
|
||||
Poco::DigestEngine::Digest rawS(ecdsaSig.rawS());
|
||||
jwtSig.insert(jwtSig.end(), rawS.begin(), rawS.end());
|
||||
return jwtSig;
|
||||
|
||||
}
|
||||
|
||||
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
|
||||
{
|
||||
if (!signer.getECKey()) throw SignatureVerificationException("No EC key available");
|
||||
|
||||
Poco::DigestEngine::Digest rawR(signature.begin(), signature.begin() + signature.size() / 2);
|
||||
Poco::DigestEngine::Digest rawS(signature.begin() + signature.size() / 2, signature.end());
|
||||
|
||||
Poco::Crypto::ECDSASignature ecdsaSig(rawR, rawS);
|
||||
Poco::DigestEngine::Digest derSig = ecdsaSig.toDER();
|
||||
|
||||
Poco::Crypto::ECDSADigestEngine ecdsa(*signer.getECKey(), _digestType);
|
||||
ecdsa.update(header);
|
||||
ecdsa.update('.');
|
||||
ecdsa.update(payload);
|
||||
return ecdsa.verify(derSig);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _digestType;
|
||||
};
|
||||
|
||||
|
||||
class ES256: public ECDSAAlgorithm
|
||||
{
|
||||
public:
|
||||
ES256():
|
||||
ECDSAAlgorithm(Algorithm::SHA256)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ES384: public ECDSAAlgorithm
|
||||
{
|
||||
public:
|
||||
ES384():
|
||||
ECDSAAlgorithm(Algorithm::SHA384)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ES512: public ECDSAAlgorithm
|
||||
{
|
||||
public:
|
||||
ES512():
|
||||
ECDSAAlgorithm(Algorithm::SHA512)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// AlgorithmFactory
|
||||
//
|
||||
|
||||
|
||||
class AlgorithmFactory: public Poco::DynamicFactory<Algorithm>
|
||||
{
|
||||
public:
|
||||
AlgorithmFactory()
|
||||
{
|
||||
registerClass<HS256>(Signer::ALGO_HS256);
|
||||
registerClass<HS384>(Signer::ALGO_HS384);
|
||||
registerClass<HS512>(Signer::ALGO_HS512);
|
||||
|
||||
registerClass<RS256>(Signer::ALGO_RS256);
|
||||
registerClass<RS384>(Signer::ALGO_RS384);
|
||||
registerClass<RS512>(Signer::ALGO_RS512);
|
||||
|
||||
registerClass<ES256>(Signer::ALGO_ES256);
|
||||
registerClass<ES384>(Signer::ALGO_ES384);
|
||||
registerClass<ES512>(Signer::ALGO_ES512);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Signer
|
||||
//
|
||||
|
||||
|
||||
const std::string Signer::ALGO_NONE("none");
|
||||
const std::string Signer::ALGO_HS256("HS256");
|
||||
const std::string Signer::ALGO_HS384("HS384");
|
||||
const std::string Signer::ALGO_HS512("HS512");
|
||||
const std::string Signer::ALGO_RS256("RS256");
|
||||
const std::string Signer::ALGO_RS384("RS384");
|
||||
const std::string Signer::ALGO_RS512("RS512");
|
||||
const std::string Signer::ALGO_ES256("ES256");
|
||||
const std::string Signer::ALGO_ES384("ES384");
|
||||
const std::string Signer::ALGO_ES512("ES512");
|
||||
|
||||
|
||||
Signer::Signer()
|
||||
{
|
||||
_algorithms.insert(ALGO_HS256);
|
||||
}
|
||||
|
||||
|
||||
Signer::Signer(const std::string& hmacKey):
|
||||
_hmacKey(hmacKey)
|
||||
{
|
||||
_algorithms.insert(ALGO_HS256);
|
||||
}
|
||||
|
||||
|
||||
Signer::Signer(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pRSAKey):
|
||||
_pRSAKey(pRSAKey)
|
||||
{
|
||||
_algorithms.insert(ALGO_HS256);
|
||||
}
|
||||
|
||||
|
||||
Signer::Signer(const Poco::SharedPtr<Poco::Crypto::ECKey>& pECKey):
|
||||
_pECKey(pECKey)
|
||||
{
|
||||
_algorithms.insert(ALGO_HS256);
|
||||
}
|
||||
|
||||
|
||||
Signer::~Signer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::setAlgorithms(const std::set<std::string>& algorithms)
|
||||
{
|
||||
_algorithms = algorithms;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::addAlgorithm(const std::string& algorithm)
|
||||
{
|
||||
_algorithms.insert(algorithm);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::addAllAlgorithms()
|
||||
{
|
||||
_algorithms.insert(ALGO_HS256);
|
||||
_algorithms.insert(ALGO_HS384);
|
||||
_algorithms.insert(ALGO_HS512);
|
||||
|
||||
_algorithms.insert(ALGO_RS256);
|
||||
_algorithms.insert(ALGO_RS384);
|
||||
_algorithms.insert(ALGO_RS512);
|
||||
|
||||
_algorithms.insert(ALGO_ES256);
|
||||
_algorithms.insert(ALGO_ES384);
|
||||
_algorithms.insert(ALGO_ES512);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::setHMACKey(const std::string& key)
|
||||
{
|
||||
_hmacKey = key;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::setRSAKey(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pKey)
|
||||
{
|
||||
_pRSAKey = pKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Signer& Signer::setECKey(const Poco::SharedPtr<Poco::Crypto::ECKey>& pKey)
|
||||
{
|
||||
_pECKey = pKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
std::string Signer::sign(Token& token, const std::string& algorithm) const
|
||||
{
|
||||
AlgorithmFactory factory;
|
||||
if (!factory.isClass(algorithm)) throw UnsupportedAlgorithmException(algorithm);
|
||||
|
||||
token.setAlgorithm(algorithm);
|
||||
|
||||
std::string header = Serializer::serialize(token.header());
|
||||
std::string payload = Serializer::serialize(token.payload());
|
||||
|
||||
Algorithm::Ptr pAlgorithm = factory.createInstance(algorithm);
|
||||
Poco::DigestEngine::Digest digest = pAlgorithm->sign(*this, header, payload);
|
||||
|
||||
std::string signature = encode(digest);
|
||||
token.sign(signature);
|
||||
std::string jwt = header;
|
||||
jwt += '.';
|
||||
jwt += payload;
|
||||
jwt += '.';
|
||||
jwt += signature;
|
||||
return jwt;
|
||||
}
|
||||
|
||||
|
||||
Token Signer::verify(const std::string& jwt) const
|
||||
{
|
||||
Token token;
|
||||
if (tryVerify(jwt, token))
|
||||
return token;
|
||||
else
|
||||
throw SignatureVerificationException();
|
||||
}
|
||||
|
||||
|
||||
bool Signer::tryVerify(const std::string& jwt, Token& token) const
|
||||
{
|
||||
std::vector<std::string> parts = Serializer::split(jwt);
|
||||
if (parts.size() < 3) throw ParseException("Not a valid JWT", jwt);
|
||||
|
||||
token.assign(parts[0], parts[1], parts[2]);
|
||||
std::string algorithm = token.getAlgorithm();
|
||||
|
||||
if (_algorithms.find(algorithm) == _algorithms.end()) throw UnallowedAlgorithmException(algorithm);
|
||||
|
||||
AlgorithmFactory factory;
|
||||
if (!factory.isClass(algorithm)) throw UnsupportedAlgorithmException(algorithm);
|
||||
|
||||
Algorithm::Ptr pAlgorithm = factory.createInstance(algorithm);
|
||||
|
||||
return pAlgorithm->verify(*this, parts[0], parts[1], decode(parts[2]));
|
||||
}
|
||||
|
||||
|
||||
std::string Signer::encode(const Poco::DigestEngine::Digest& digest)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
Poco::Base64Encoder encoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
|
||||
encoder.write(reinterpret_cast<const char*>(&digest[0]), digest.size());
|
||||
encoder.close();
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
Poco::DigestEngine::Digest Signer::decode(const std::string& signature)
|
||||
{
|
||||
Poco::DigestEngine::Digest digest;
|
||||
digest.reserve(64);
|
||||
Poco::MemoryInputStream stream(signature.data(), signature.size());
|
||||
Poco::Base64Decoder decoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
|
||||
int ch = decoder.get();
|
||||
while (ch != -1)
|
||||
{
|
||||
digest.push_back(static_cast<unsigned char>(static_cast<unsigned>(ch)));
|
||||
ch = decoder.get();
|
||||
}
|
||||
return digest;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
198
vendor/POCO/JWT/src/Token.cpp
vendored
Normal file
198
vendor/POCO/JWT/src/Token.cpp
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
//
|
||||
// Token.cpp
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Token
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/JWT/Token.h"
|
||||
#include "Poco/JWT/Serializer.h"
|
||||
#include "Poco/JWT/JWTException.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
const std::string Token::CLAIM_ISSUER("iss");
|
||||
const std::string Token::CLAIM_SUBJECT("sub");
|
||||
const std::string Token::CLAIM_AUDIENCE("aud");
|
||||
const std::string Token::CLAIM_EXPIRATION("exp");
|
||||
const std::string Token::CLAIM_NOT_BEFORE("nbf");
|
||||
const std::string Token::CLAIM_ISSUED_AT("iat");
|
||||
const std::string Token::CLAIM_JWT_ID("jti");
|
||||
const std::string Token::CLAIM_TYPE("typ");
|
||||
const std::string Token::CLAIM_ALGORITHM("alg");
|
||||
const std::string Token::CLAIM_CONTENT_TYPE("cty");
|
||||
const std::string Token::EMPTY;
|
||||
|
||||
|
||||
Token::Token():
|
||||
_pHeader(new Poco::JSON::Object),
|
||||
_pPayload(new Poco::JSON::Object)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Token::Token(const std::string& token)
|
||||
{
|
||||
std::vector<std::string> parts = Serializer::split(token);
|
||||
if (parts.size() < 3) throw ParseException("Not a valid JWT", token);
|
||||
_pHeader = Serializer::deserialize(parts[0]);
|
||||
_pPayload = Serializer::deserialize(parts[1]);
|
||||
_signature = parts[2];
|
||||
}
|
||||
|
||||
|
||||
Token::Token(const Token& token):
|
||||
_pHeader(new Poco::JSON::Object(*token._pHeader)),
|
||||
_pPayload(new Poco::JSON::Object(*token._pPayload)),
|
||||
_signature(token._signature)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Token::Token(Token&& token) noexcept:
|
||||
_pHeader(std::move(token._pHeader)),
|
||||
_pPayload(std::move(token._pPayload)),
|
||||
_signature(std::move(token._signature))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Token::Token(const std::string& header, const std::string& payload, const std::string& signature)
|
||||
{
|
||||
assign(header, payload, signature);
|
||||
}
|
||||
|
||||
|
||||
Token::~Token()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Token& Token::operator = (const Token& token)
|
||||
{
|
||||
if (&token != this)
|
||||
{
|
||||
Poco::JSON::Object::Ptr pHeader = new Poco::JSON::Object(*token._pHeader);
|
||||
Poco::JSON::Object::Ptr pPayload = new Poco::JSON::Object(*token._pPayload);
|
||||
std::string signature = token._signature;
|
||||
|
||||
std::swap(_pHeader, pHeader);
|
||||
std::swap(_pPayload, pPayload);
|
||||
std::swap(_signature, signature);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Token& Token::operator = (Token&& token) noexcept
|
||||
{
|
||||
_pHeader = std::move(token._pHeader);
|
||||
_pPayload = std::move(token._pPayload);
|
||||
_signature = std::move(token._signature);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Token& Token::operator = (const std::string& token)
|
||||
{
|
||||
std::vector<std::string> parts = Serializer::split(token);
|
||||
if (parts.size() < 3) throw ParseException("Not a valid JWT", token);
|
||||
assign(parts[0], parts[1], parts[2]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Token::assign(const std::string& header, const std::string& payload, const std::string& signature)
|
||||
{
|
||||
Poco::JSON::Object::Ptr pHeader = Serializer::deserialize(header);
|
||||
Poco::JSON::Object::Ptr pPayload = Serializer::deserialize(payload);
|
||||
std::string aSignature = signature;
|
||||
|
||||
std::swap(_pHeader, pHeader);
|
||||
std::swap(_pPayload, pPayload);
|
||||
std::swap(_signature, aSignature);
|
||||
}
|
||||
|
||||
|
||||
std::string Token::toString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
Serializer::serialize(*_pHeader, stream);
|
||||
stream << '.';
|
||||
Serializer::serialize(*_pPayload, stream);
|
||||
stream << '.';
|
||||
stream << _signature;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
void Token::setAudience(const std::vector<std::string>& audience)
|
||||
{
|
||||
Poco::JSON::Array::Ptr pArray = new Poco::JSON::Array;
|
||||
for (std::vector<std::string>::const_iterator it = audience.begin(); it != audience.end(); ++it)
|
||||
{
|
||||
pArray->add(*it);
|
||||
}
|
||||
_pPayload->set(CLAIM_AUDIENCE, pArray);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> Token::getAudience() const
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
if (_pPayload->has(CLAIM_AUDIENCE))
|
||||
{
|
||||
if (_pPayload->isArray(CLAIM_AUDIENCE))
|
||||
{
|
||||
Poco::JSON::Array::Ptr pArray = _pPayload->getArray(CLAIM_AUDIENCE);
|
||||
if (pArray)
|
||||
{
|
||||
for (unsigned i = 0; i < pArray->size(); i++)
|
||||
{
|
||||
result.push_back(pArray->getElement<std::string>(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(_pPayload->getValue<std::string>(CLAIM_AUDIENCE));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Token::setTimestamp(const std::string& claim, const Poco::Timestamp& ts)
|
||||
{
|
||||
double epochSeconds = static_cast<double>(ts.epochMicroseconds())/Poco::Timestamp::resolution();
|
||||
_pPayload->set(claim, epochSeconds);
|
||||
}
|
||||
|
||||
|
||||
Poco::Timestamp Token::getTimestamp(const std::string& claim) const
|
||||
{
|
||||
double epochSeconds = _pPayload->optValue(claim, 0.0);
|
||||
Poco::Timestamp::TimeVal tv = static_cast<Poco::Timestamp::TimeVal>(epochSeconds*Poco::Timestamp::resolution());
|
||||
return Poco::Timestamp(tv);
|
||||
}
|
||||
|
||||
|
||||
void Token::sign(const std::string& signature)
|
||||
{
|
||||
_signature = signature;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
Reference in New Issue
Block a user