mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
added JWT library
This commit is contained in:
parent
d25b665194
commit
6c828018df
@ -119,7 +119,7 @@ if(ENABLE_DATA_POSTGRESQL)
|
||||
else()
|
||||
find_package(PostgreSQL)
|
||||
endif()
|
||||
|
||||
|
||||
if(PostgreSQL_FOUND)
|
||||
option(ENABLE_DATA "Enable SQL" ON)
|
||||
option(ENABLE_DATA_POSTGRESQL "Enable SQL PosgreSQL" ON)
|
||||
@ -154,6 +154,7 @@ option(ENABLE_PDF "Enable PDF" OFF)
|
||||
option(ENABLE_UTIL "Enable Util" ON)
|
||||
option(ENABLE_NET "Enable Net" ON)
|
||||
option(ENABLE_NETSSL_WIN "Enable NetSSL Windows" OFF)
|
||||
option(ENABLE_JWT "Enable JWT" OFF)
|
||||
option(ENABLE_SEVENZIP "Enable SevenZip" OFF)
|
||||
option(ENABLE_ZIP "Enable Zip" ON)
|
||||
option(ENABLE_CPPPARSER "Enable C++ parser" OFF)
|
||||
@ -227,7 +228,7 @@ endif()
|
||||
|
||||
if(ENABLE_PAGECOMPILER)
|
||||
set(ENABLE_NET ON CACHE BOOL "Enable Net" FORCE)
|
||||
set(ENABLE_UTIL ON CACHE BOOL "Enable Util" FORCE)
|
||||
set(ENABLE_UTIL ON CACHE BOOL "Enable Util" FORCE)
|
||||
endif()
|
||||
|
||||
if(ENABLE_MONGODB OR ENABLE_REDIS)
|
||||
@ -269,6 +270,11 @@ if(ENABLE_NET AND ENABLE_TESTS)
|
||||
set(ENABLE_UTIL ON CACHE BOOL "Enable Util" FORCE)
|
||||
endif()
|
||||
|
||||
if(ENABLE_JWT)
|
||||
set(ENABLE_CRYPTO ON CACHE BOOL "Enable Crypto" FORCE)
|
||||
set(ENABLE_JSON ON CACHE BOOL "Enable JSON" FORCE)
|
||||
endif()
|
||||
|
||||
if(ENABLE_PDF)
|
||||
set(ENABLE_UTIL ON CACHE BOOL "Enable Util" FORCE)
|
||||
set(ENABLE_XML ON CACHE BOOL "Enable XML" FORCE)
|
||||
@ -282,7 +288,7 @@ endif()
|
||||
|
||||
if(ENABLE_SEVENZIP OR ENABLE_ZIP)
|
||||
set(ENABLE_UTIL ON CACHE BOOL "Enable Util" FORCE)
|
||||
set(ENABLE_XML ON CACHE BOOL "Enable XML" FORCE)
|
||||
set(ENABLE_XML ON CACHE BOOL "Enable XML" FORCE)
|
||||
endif()
|
||||
|
||||
if(ENABLE_UTIL AND ENABLE_TESTS)
|
||||
@ -316,6 +322,11 @@ if(ENABLE_NET)
|
||||
list(APPEND Poco_COMPONENTS "Net")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${PROJECT_SOURCE_DIR}/JWT AND ENABLE_JWT)
|
||||
add_subdirectory(JWT)
|
||||
list(APPEND Poco_COMPONENTS "JWT")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${PROJECT_SOURCE_DIR}/MongoDB AND ENABLE_MONGODB)
|
||||
add_subdirectory(MongoDB)
|
||||
list(APPEND Poco_COMPONENTS "MongoDB")
|
||||
@ -366,7 +377,7 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/Zip AND ENABLE_ZIP)
|
||||
list(APPEND Poco_COMPONENTS "Zip")
|
||||
endif()
|
||||
|
||||
if(APRUTIL_FOUND AND APACHE_FOUND AND
|
||||
if(APRUTIL_FOUND AND APACHE_FOUND AND
|
||||
EXISTS ${PROJECT_SOURCE_DIR}/ApacheConnector AND ENABLE_APACHECONNECTOR)
|
||||
add_subdirectory(ApacheConnector)
|
||||
list(APPEND Poco_COMPONENTS "ApacheConnector")
|
||||
@ -447,7 +458,7 @@ if(POCO_UNBUNDLED)
|
||||
DESTINATION "${PocoConfigPackageLocation}")
|
||||
install(FILES cmake/V39/FindEXPAT.cmake
|
||||
DESTINATION "${PocoConfigPackageLocation}/V39")
|
||||
install(FILES cmake/V313/FindSQLite3.cmake
|
||||
install(FILES cmake/V313/FindSQLite3.cmake
|
||||
DESTINATION "${PocoConfigPackageLocation}/V313")
|
||||
endif()
|
||||
|
||||
|
@ -40,7 +40,7 @@ class Crypto_API ECDSADigestEngine: public Poco::DigestEngine
|
||||
/// signed. Then, the hash value is encrypted, using
|
||||
/// the ECDSA private key.
|
||||
///
|
||||
/// To verify a signature, pass it to the verify()
|
||||
/// To verify a signature, pass it to the verify()
|
||||
/// member function. It will decrypt the signature
|
||||
/// using the ECDSA public key and compare the resulting
|
||||
/// hash with the actual hash of the data.
|
||||
@ -64,11 +64,11 @@ public:
|
||||
void reset();
|
||||
/// Resets the engine so that a new
|
||||
/// digest can be computed.
|
||||
|
||||
|
||||
const DigestEngine::Digest& digest();
|
||||
/// Finishes the computation of the digest
|
||||
/// Finishes the computation of the digest
|
||||
/// (the first time it's called) and
|
||||
/// returns the message digest.
|
||||
/// returns the message digest.
|
||||
///
|
||||
/// Can be called multiple times.
|
||||
|
||||
@ -95,6 +95,35 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class Crypto_API ECDSASignature
|
||||
/// A helper class for dealing with ECDSA signatures.
|
||||
{
|
||||
public:
|
||||
typedef std::vector<unsigned char> ByteVec;
|
||||
|
||||
explicit ECDSASignature(const ByteVec& derSignature);
|
||||
/// Creates the ECDSASignature from a DER-encoded signature.
|
||||
|
||||
ECDSASignature(const ByteVec& rawR, const ByteVec& rawS);
|
||||
/// Creates the ECDSASignature from raw r and s values.
|
||||
|
||||
~ECDSASignature();
|
||||
/// Destroys the ECDSASignature.
|
||||
|
||||
ByteVec toDER() const;
|
||||
/// Returns a buffer containing the DER-encoded signature.
|
||||
|
||||
ByteVec rawR() const;
|
||||
/// Returns a raw P value.
|
||||
|
||||
ByteVec rawS() const;
|
||||
/// Returns a raw Q value.
|
||||
|
||||
private:
|
||||
ECDSA_SIG* _pSig;
|
||||
};
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
#include "Poco/Crypto/ECDSADigestEngine.h"
|
||||
#include "Poco/Crypto/CryptoException.h"
|
||||
#include <openssl/ecdsa.h>
|
||||
|
||||
|
||||
@ -21,6 +22,11 @@ namespace Poco {
|
||||
namespace Crypto {
|
||||
|
||||
|
||||
//
|
||||
// ECDSADigestEngine
|
||||
//
|
||||
|
||||
|
||||
ECDSADigestEngine::ECDSADigestEngine(const ECKey& key, const std::string &name):
|
||||
_key(key),
|
||||
_engine(name)
|
||||
@ -46,7 +52,7 @@ void ECDSADigestEngine::reset()
|
||||
_signature.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
const DigestEngine::Digest& ECDSADigestEngine::digest()
|
||||
{
|
||||
if (_digest.empty())
|
||||
@ -97,4 +103,104 @@ void ECDSADigestEngine::updateImpl(const void* data, std::size_t length)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ECDSASignature
|
||||
//
|
||||
|
||||
|
||||
ECDSASignature::ECDSASignature(const ByteVec& derSignature)
|
||||
{
|
||||
poco_assert (!derSignature.empty());
|
||||
|
||||
const unsigned char* p = &derSignature[0];
|
||||
_pSig = d2i_ECDSA_SIG(0, &p, derSignature.size());
|
||||
if (!_pSig)
|
||||
throw OpenSSLException();
|
||||
}
|
||||
|
||||
|
||||
ECDSASignature::ECDSASignature(const ByteVec& rawR, const ByteVec& rawS):
|
||||
_pSig(ECDSA_SIG_new())
|
||||
{
|
||||
poco_assert (!rawR.empty() && !rawS.empty());
|
||||
|
||||
if (!_pSig) throw CryptoException("cannot allocate ECDSA signature");
|
||||
|
||||
try
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
ECDSA_SIG_set0(_pSig,
|
||||
BN_bin2bn(&rawR[0], rawR.size(), 0),
|
||||
BN_bin2bn(&rawS[0], rawS.size(), 0));
|
||||
if (ECDSA_SIG_get0_r(_pSig) == 0 || ECDSA_SIG_get0_s(_pSig) == 0)
|
||||
throw CryptoException("failed to decode R and S values");
|
||||
#else
|
||||
if (!BN_bin2bn(&rawR[0], rawR.size(), _pSig->r))
|
||||
throw OpenSSLException();
|
||||
if (!BN_bin2bn(&rawS[0], rawS.size(), _pSig->s))
|
||||
throw OpenSSLException();
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ECDSA_SIG_free(_pSig);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ECDSASignature::~ECDSASignature()
|
||||
{
|
||||
ECDSA_SIG_free(_pSig);
|
||||
}
|
||||
|
||||
|
||||
ECDSASignature::ByteVec ECDSASignature::toDER() const
|
||||
{
|
||||
int size = i2d_ECDSA_SIG(_pSig, 0);
|
||||
if (size > 0)
|
||||
{
|
||||
ByteVec buffer(size);
|
||||
unsigned char* p = &buffer[0];
|
||||
i2d_ECDSA_SIG(_pSig, &p);
|
||||
return buffer;
|
||||
}
|
||||
else throw OpenSSLException();
|
||||
}
|
||||
|
||||
|
||||
ECDSASignature::ByteVec ECDSASignature::rawR() const
|
||||
{
|
||||
ByteVec buffer;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
const BIGNUM* pR = ECDSA_SIG_get0_r(_pSig);
|
||||
#else
|
||||
const BIGNUM* pR = _pSig->r;
|
||||
#endif
|
||||
if (pR)
|
||||
{
|
||||
buffer.resize(BN_num_bytes(pR));
|
||||
BN_bn2bin(pR, &buffer[0]);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
ECDSASignature::ByteVec ECDSASignature::rawS() const
|
||||
{
|
||||
ByteVec buffer;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
const BIGNUM* pS = ECDSA_SIG_get0_s(_pSig);
|
||||
#else
|
||||
const BIGNUM* pS = _pSig->s;
|
||||
#endif
|
||||
if (pS)
|
||||
{
|
||||
buffer.resize(BN_num_bytes(pS));
|
||||
BN_bn2bin(pS, &buffer[0]);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
37
JWT/CMakeLists.txt
Normal file
37
JWT/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
# Sources
|
||||
file(GLOB SRCS_G "src/*.cpp")
|
||||
POCO_SOURCES_AUTO( SRCS ${SRCS_G})
|
||||
|
||||
# Headers
|
||||
file(GLOB_RECURSE HDRS_G "include/*.h" )
|
||||
POCO_HEADERS_AUTO( SRCS ${HDRS_G})
|
||||
|
||||
# Version Resource
|
||||
if(MSVC AND NOT POCO_STATIC)
|
||||
source_group("Resources" FILES ${CMAKE_SOURCE_DIR}/DLLVersion.rc)
|
||||
list(APPEND SRCS ${CMAKE_SOURCE_DIR}/DLLVersion.rc)
|
||||
endif()
|
||||
|
||||
add_library(JWT ${SRCS} )
|
||||
add_library(Poco::JWT ALIAS JWT)
|
||||
set_target_properties( JWT
|
||||
PROPERTIES
|
||||
VERSION ${SHARED_LIBRARY_VERSION} SOVERSION ${SHARED_LIBRARY_VERSION}
|
||||
OUTPUT_NAME PocoJWT
|
||||
DEFINE_SYMBOL JWT_EXPORTS
|
||||
)
|
||||
|
||||
target_link_libraries(JWT PUBLIC Poco::JSON Poco::Crypto)
|
||||
target_include_directories(JWT
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
POCO_INSTALL(JWT)
|
||||
POCO_GENERATE_PACKAGE(JWT)
|
||||
|
||||
if (ENABLE_TESTS)
|
||||
add_subdirectory(testsuite)
|
||||
endif ()
|
15
JWT/Makefile
Normal file
15
JWT/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# Makefile for Poco JWT
|
||||
#
|
||||
|
||||
include $(POCO_BASE)/build/rules/global
|
||||
|
||||
objects = Token Signer Serializer JWTException
|
||||
|
||||
target = PocoJWT
|
||||
target_version = $(LIBVERSION)
|
||||
target_libs = PocoCrypto PocoJSON PocoFoundation
|
||||
|
||||
include $(POCO_BASE)/build/rules/lib
|
5
JWT/cmake/PocoJWTConfig.cmake
Normal file
5
JWT/cmake/PocoJWTConfig.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(PocoFoundation)
|
||||
find_dependency(PocoJSON)
|
||||
find_dependency(PocoCrypto)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/PocoJWTTargets.cmake")
|
62
JWT/include/Poco/JWT/JWT.h
Normal file
62
JWT/include/Poco/JWT/JWT.h
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// JWT.h
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: JWT
|
||||
//
|
||||
// Basic definitions for the Poco JWT library.
|
||||
// This file must be the first file included by every other JWT
|
||||
// header file.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWT_JWT_INCLUDED
|
||||
#define JWT_JWT_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
|
||||
|
||||
//
|
||||
// The following block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the JWT_EXPORTS
|
||||
// symbol defined on the command line. this symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// JWT_API functions as being imported from a DLL, whereas this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
//
|
||||
#if defined(_WIN32) && defined(POCO_DLL)
|
||||
#if defined(JWT_EXPORTS)
|
||||
#define JWT_API __declspec(dllexport)
|
||||
#else
|
||||
#define JWT_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(JWT_API)
|
||||
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define JWT_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define JWT_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Automatically link JWT library.
|
||||
//
|
||||
#if defined(_MSC_VER)
|
||||
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(JWT_EXPORTS)
|
||||
#pragma comment(lib, "PocoJWT" POCO_LIB_SUFFIX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // JWT_JWT_INCLUDED
|
41
JWT/include/Poco/JWT/JWTException.h
Normal file
41
JWT/include/Poco/JWT/JWTException.h
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// JWTException.h
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: JWTException
|
||||
//
|
||||
// Definition of the JWTException class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWT_JWTException_INCLUDED
|
||||
#define JWT_JWTException_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, JWTException, Poco::Exception)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, ParseException, JWTException)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, UnsupportedAlgorithmException, JWTException)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, UnallowedAlgorithmException, JWTException)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, SignatureException, JWTException)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, SignatureVerificationException, SignatureException)
|
||||
POCO_DECLARE_EXCEPTION(JWT_API, SignatureGenerationException, SignatureException)
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
||||
|
||||
|
||||
#endif // JWT_JWTException_INCLUDED
|
53
JWT/include/Poco/JWT/Serializer.h
Normal file
53
JWT/include/Poco/JWT/Serializer.h
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// Serializer.h
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Serializer
|
||||
//
|
||||
// Definition of the Serializer class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWT_Serializer_INCLUDED
|
||||
#define JWT_Serializer_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
class JWT_API Serializer
|
||||
/// A helper class for serializing and deserializing JWTs.
|
||||
{
|
||||
public:
|
||||
static std::string serialize(const Poco::JSON::Object& object);
|
||||
/// Serializes and base64-encodes a JSON object.
|
||||
|
||||
static void serialize(const Poco::JSON::Object& object, std::ostream& stream);
|
||||
/// Serializes and base64-encodes a JSON object.
|
||||
|
||||
static Poco::JSON::Object::Ptr deserialize(const std::string& serialized);
|
||||
/// Attempts to deserialize a base64-encoded serialized JSON object.
|
||||
|
||||
static Poco::JSON::Object::Ptr deserialize(std::istream& stream);
|
||||
/// Attempts to deserialize a base64-encoded serialized JSON object.
|
||||
|
||||
static std::vector<std::string> split(const std::string& token);
|
||||
/// Splits a serialized JWT into its components.
|
||||
};
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
||||
|
||||
|
||||
#endif // JWT_Serializer_INCLUDED
|
196
JWT/include/Poco/JWT/Signer.h
Normal file
196
JWT/include/Poco/JWT/Signer.h
Normal file
@ -0,0 +1,196 @@
|
||||
//
|
||||
// Signer.h
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Signer
|
||||
//
|
||||
// Definition of the Signer class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWT_Signer_INCLUDED
|
||||
#define JWT_Signer_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "Poco/JWT/Token.h"
|
||||
#include "Poco/Crypto/RSAKey.h"
|
||||
#include "Poco/Crypto/ECKey.h"
|
||||
#include "Poco/DigestEngine.h"
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
class JWT_API Signer
|
||||
/// This class signs and verifies the signature of JSON Web Tokens.
|
||||
///
|
||||
/// The following signing algorithms are supported:
|
||||
/// - HS256 (HMAC using SHA256)
|
||||
/// - HS384 (HMAC using SHA384)
|
||||
/// - HS512 (HMAC using SHA512)
|
||||
/// - RS256 (RSA SSA PKCS1 v1.5 using SHA256)
|
||||
/// - RS384 (RSA SSA PKCS1 v1.5 using SHA384)
|
||||
/// - RS512 (RSA SSA PKCS1 v1.5 using SHA512)
|
||||
/// - ES256 (ECDSA using P-256 and SHA-256)
|
||||
/// - ES384 (ECDSA using P-256 and SHA-384)
|
||||
/// - ES512 (ECDSA using P-256 and SHA-512)
|
||||
{
|
||||
public:
|
||||
Signer();
|
||||
/// Creates a Signer.
|
||||
///
|
||||
/// For signing and verification, a key must be set using the
|
||||
/// setHMACKey(), setRSAKey() or setECKey() methods.
|
||||
///
|
||||
/// Sets HS256 as the only allowed algorithm.
|
||||
/// Call setAlgorithms() or addAlgorithm() to allow additional
|
||||
/// algorithms for verification.
|
||||
|
||||
explicit Signer(const std::string& hmacKey);
|
||||
/// Creates the Signer using the given secret/key for HMAC-based signing and verification.
|
||||
///
|
||||
/// Sets HS256 as the only allowed algorithm.
|
||||
/// Call setAlgorithms() or addAlgorithm() to allow additional
|
||||
/// algorithms for verification.
|
||||
|
||||
explicit Signer(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pRSAKey);
|
||||
/// Creates the Signer using the given secret/key for RSA-based signing and verification.
|
||||
///
|
||||
/// Sets HS256 as the only allowed algorithm.
|
||||
/// Call setAlgorithms() or addAlgorithm() to allow additional
|
||||
/// algorithms for verification.
|
||||
|
||||
explicit Signer(const Poco::SharedPtr<Poco::Crypto::ECKey>& pECKey);
|
||||
/// Creates the Signer using the given secret/key for EC-based signing and verification.
|
||||
///
|
||||
/// Sets HS256 as the only allowed algorithm.
|
||||
/// Call setAlgorithms() or addAlgorithm() to allow additional
|
||||
/// algorithms for verification.
|
||||
|
||||
~Signer();
|
||||
/// Destroys the Signer.
|
||||
|
||||
Signer& setAlgorithms(const std::set<std::string>& algorithms);
|
||||
/// Sets the allowed algorithms for signing.
|
||||
///
|
||||
/// When verifying JWTs, the algorithm used for signing
|
||||
/// must be one of the allowed algorithms.
|
||||
|
||||
const std::set<std::string>& getAlgorithms() const;
|
||||
/// Returns the allowed algorithms for signing.
|
||||
|
||||
Signer& addAlgorithm(const std::string& algorithm);
|
||||
/// Adds an algorithm to the set of allowed algorithms.
|
||||
|
||||
Signer& addAllAlgorithms();
|
||||
/// Adds all supported algorithm to the set of allowed algorithms.
|
||||
|
||||
Signer& setHMACKey(const std::string& key);
|
||||
/// Sets the key used for HMAC-based signing and verification.
|
||||
|
||||
const std::string getHMACKey() const;
|
||||
/// Returns the key used for HMAC-based signing and verification.
|
||||
|
||||
Signer& setRSAKey(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pKey);
|
||||
/// Sets the key used for RSA-based signing and verification.
|
||||
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> getRSAKey() const;
|
||||
/// Returns the key used for RSA-based signing and verification.
|
||||
|
||||
Signer& setECKey(const Poco::SharedPtr<Poco::Crypto::ECKey>& pKey);
|
||||
/// Sets the key used for EC-based signing and verification.
|
||||
|
||||
Poco::SharedPtr<Poco::Crypto::ECKey> getECKey() const;
|
||||
/// Returns the key used for EC-based signing and verification.
|
||||
|
||||
std::string sign(Token& token, const std::string& algorithm) const;
|
||||
/// Signs the given token using the given algorithm.
|
||||
///
|
||||
/// An appropriate key must have been provided prior to calling sign().
|
||||
///
|
||||
/// Returns the serialized JWT including the signature.
|
||||
|
||||
Token verify(const std::string& jwt) const;
|
||||
/// Verifies the given serialized JSON Web Token.
|
||||
///
|
||||
/// An appropriate key must have been provided prior to calling verify().
|
||||
///
|
||||
/// If successful, returns a Token object.
|
||||
/// If not successful, throws a SignatureVerificationException.
|
||||
|
||||
bool tryVerify(const std::string& jwt, Token& token) const;
|
||||
/// Verifies the given serialized JSON Web Token and stores
|
||||
/// it in the given Token object.
|
||||
///
|
||||
/// An appropriate key must have been provided prior to calling verify().
|
||||
///
|
||||
/// If successful, returns true, otherwise false.
|
||||
|
||||
static const std::string ALGO_NONE;
|
||||
static const std::string ALGO_HS256;
|
||||
static const std::string ALGO_HS384;
|
||||
static const std::string ALGO_HS512;
|
||||
static const std::string ALGO_RS256;
|
||||
static const std::string ALGO_RS384;
|
||||
static const std::string ALGO_RS512;
|
||||
static const std::string ALGO_ES256;
|
||||
static const std::string ALGO_ES384;
|
||||
static const std::string ALGO_ES512;
|
||||
|
||||
protected:
|
||||
static std::string encode(const Poco::DigestEngine::Digest& digest);
|
||||
static Poco::DigestEngine::Digest decode(const std::string& signature);
|
||||
|
||||
private:
|
||||
Signer(const Signer&);
|
||||
Signer& operator = (const Signer&);
|
||||
|
||||
std::set<std::string> _algorithms;
|
||||
std::string _hmacKey;
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> _pRSAKey;
|
||||
Poco::SharedPtr<Poco::Crypto::ECKey> _pECKey;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
|
||||
inline const std::set<std::string>& Signer::getAlgorithms() const
|
||||
{
|
||||
return _algorithms;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string Signer::getHMACKey() const
|
||||
{
|
||||
return _hmacKey;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::Crypto::RSAKey> Signer::getRSAKey() const
|
||||
{
|
||||
return _pRSAKey;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::Crypto::ECKey> Signer::getECKey() const
|
||||
{
|
||||
return _pECKey;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
||||
|
||||
|
||||
#endif // JWT_Signer_INCLUDED
|
336
JWT/include/Poco/JWT/Token.h
Normal file
336
JWT/include/Poco/JWT/Token.h
Normal file
@ -0,0 +1,336 @@
|
||||
//
|
||||
// Token.h
|
||||
//
|
||||
// Library: JWT
|
||||
// Package: JWT
|
||||
// Module: Token
|
||||
//
|
||||
// Definition of the Token class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWT_Token_INCLUDED
|
||||
#define JWT_Token_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace JWT {
|
||||
|
||||
|
||||
class JWT_API Token
|
||||
/// This class represents a JSON Web Token (JWT) according to RFC 7519.
|
||||
///
|
||||
/// To create and sign a JWT (using the Signer class):
|
||||
///
|
||||
/// Token token;
|
||||
/// token.setType("JWT");
|
||||
/// token.setSubject("1234567890");
|
||||
/// token.payload().set("name", std::string("John Doe"));
|
||||
/// token.setIssuedAt(Poco::Timestamp()));
|
||||
///
|
||||
/// Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
/// std::string jwt = signer.sign(token, Signer::ALGO_HS256);
|
||||
///
|
||||
/// To verify a signed token:
|
||||
///
|
||||
/// std::string jwt(
|
||||
/// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
/// "eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ."
|
||||
/// "qn9G7NwFEOjIh-7hfCUDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
///
|
||||
/// Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
/// Token token = signer.verify(jwt);
|
||||
{
|
||||
public:
|
||||
Token();
|
||||
/// Creates an empty JSON Web Token.
|
||||
|
||||
explicit Token(const std::string& token);
|
||||
/// Creates a JSON Web Token from its serialized string representation.
|
||||
|
||||
Token(const Token& token);
|
||||
/// Creates a JSON Web Token by copying another one.
|
||||
|
||||
~Token();
|
||||
/// Destroys the Token.
|
||||
|
||||
Token& operator = (const Token& token);
|
||||
/// Assignment operator.
|
||||
|
||||
Token& operator = (const std::string& token);
|
||||
/// Parses and assigns serialized JWT.
|
||||
|
||||
std::string toString() const;
|
||||
/// Returns the serialized string representation of the JSON Web Token.
|
||||
|
||||
const Poco::JSON::Object& header() const;
|
||||
/// Returns the header JSON object.
|
||||
|
||||
Poco::JSON::Object& header();
|
||||
/// Returns the header JSON object.
|
||||
|
||||
const Poco::JSON::Object& payload() const;
|
||||
/// Returns the payload JSON object.
|
||||
|
||||
Poco::JSON::Object& payload();
|
||||
/// Returns the payload JSON object.
|
||||
|
||||
const std::string& signature() const;
|
||||
/// Returns the signature string.
|
||||
|
||||
void setIssuer(const std::string& issuer);
|
||||
/// Sets the issuer ("iss" claim in payload).
|
||||
|
||||
std::string getIssuer() const;
|
||||
/// Returns the issuer, or an empty string if no issuer has been specified.
|
||||
|
||||
void setSubject(const std::string& subject);
|
||||
/// Sets the subject ("sub" claim in paylod).
|
||||
|
||||
std::string getSubject() const;
|
||||
/// Returns the subject, or an empty string if no issuer has been specified.
|
||||
|
||||
void setAudience(const std::string& audience);
|
||||
/// Sets the audience ("aud" claim in payload) to a single value.
|
||||
|
||||
void setAudience(const std::vector<std::string>& audience);
|
||||
/// Sets the audience ("aud" claim in payload).
|
||||
|
||||
std::vector<std::string> getAudience() const;
|
||||
/// Returns the audience.
|
||||
|
||||
void setExpiration(const Poco::Timestamp& expiration);
|
||||
/// Sets the expiration ("exp" claim in payload).
|
||||
|
||||
Poco::Timestamp getExpiration() const;
|
||||
/// Returns the expiration, or a zero Poco::Timestamp if no expiration has been specified.
|
||||
|
||||
void setNotBefore(const Poco::Timestamp& notBefore);
|
||||
/// Sets the not-before time ("nbf" claim in payload).
|
||||
|
||||
Poco::Timestamp getNotBefore() const;
|
||||
/// Returns the not-before time, or a zero Poco::Timestamp if no not-before time has been specified.
|
||||
|
||||
void setIssuedAt(const Poco::Timestamp& issuedAt);
|
||||
/// Sets the issued-at time ("iat" claim in payload).
|
||||
|
||||
Poco::Timestamp getIssuedAt() const;
|
||||
/// Returns the issued-at time, or a zero Poco::Timestamp if no issued-at time has been specified.
|
||||
|
||||
void setId(const std::string& id);
|
||||
/// Sets the JWT ID ("jti" claim in payload).
|
||||
|
||||
std::string getId() const;
|
||||
/// Returns the JWT ID, or an empty string if no JWT ID has been specified.
|
||||
|
||||
void setType(const std::string& type);
|
||||
/// Sets the JWT type ("typ" claim in payload).
|
||||
|
||||
std::string getType() const;
|
||||
/// Returns the JWT type or an empty string if no type has been specified.
|
||||
|
||||
void setAlgorithm(const std::string& algorithm);
|
||||
/// Sets the JWT signature algorithm ("alg" claim in header).
|
||||
|
||||
std::string getAlgorithm() const;
|
||||
/// Returns the JWT signature algorithm, or an empty string if no algorithm has been specified.
|
||||
|
||||
void setContentType(const std::string& contentType);
|
||||
/// Sets the JWT content type ("cty" claim in header").
|
||||
|
||||
std::string getContentType() const;
|
||||
/// Returns the JWT content type, or an empty string if no content type has been specified.
|
||||
|
||||
static const std::string CLAIM_ISSUER;
|
||||
static const std::string CLAIM_SUBJECT;
|
||||
static const std::string CLAIM_AUDIENCE;
|
||||
static const std::string CLAIM_EXPIRATION;
|
||||
static const std::string CLAIM_NOT_BEFORE;
|
||||
static const std::string CLAIM_ISSUED_AT;
|
||||
static const std::string CLAIM_JWT_ID;
|
||||
static const std::string CLAIM_TYPE;
|
||||
static const std::string CLAIM_ALGORITHM;
|
||||
static const std::string CLAIM_CONTENT_TYPE;
|
||||
|
||||
protected:
|
||||
Token(const std::string& header, const std::string& payload, const std::string& signature);
|
||||
|
||||
void sign(const std::string& signature);
|
||||
void setTimestamp(const std::string& claim, const Poco::Timestamp& ts);
|
||||
Poco::Timestamp getTimestamp(const std::string& claim) const;
|
||||
void assign(const std::string& header, const std::string& payload, const std::string& signature);
|
||||
|
||||
private:
|
||||
Poco::JSON::Object::Ptr _pHeader;
|
||||
Poco::JSON::Object::Ptr _pPayload;
|
||||
std::string _signature;
|
||||
|
||||
static const std::string EMPTY;
|
||||
|
||||
friend class Signer;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
|
||||
inline const Poco::JSON::Object& Token::header() const
|
||||
{
|
||||
return *_pHeader;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::JSON::Object& Token::header()
|
||||
{
|
||||
return *_pHeader;
|
||||
}
|
||||
|
||||
|
||||
inline const Poco::JSON::Object& Token::payload() const
|
||||
{
|
||||
return *_pPayload;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::JSON::Object& Token::payload()
|
||||
{
|
||||
return *_pPayload;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& Token::signature() const
|
||||
{
|
||||
return _signature;
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setIssuer(const std::string& issuer)
|
||||
{
|
||||
_pPayload->set(CLAIM_ISSUER, issuer);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getIssuer() const
|
||||
{
|
||||
return _pPayload->optValue(CLAIM_ISSUER, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setSubject(const std::string& subject)
|
||||
{
|
||||
_pPayload->set(CLAIM_SUBJECT, subject);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getSubject() const
|
||||
{
|
||||
return _pPayload->optValue(CLAIM_SUBJECT, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setAudience(const std::string& audience)
|
||||
{
|
||||
_pPayload->set(CLAIM_AUDIENCE, audience);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setExpiration(const Poco::Timestamp& expiration)
|
||||
{
|
||||
setTimestamp(CLAIM_EXPIRATION, expiration);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Timestamp Token::getExpiration() const
|
||||
{
|
||||
return getTimestamp(CLAIM_EXPIRATION);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setNotBefore(const Poco::Timestamp& notBefore)
|
||||
{
|
||||
setTimestamp(CLAIM_NOT_BEFORE, notBefore);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Timestamp Token::getNotBefore() const
|
||||
{
|
||||
return getTimestamp(CLAIM_NOT_BEFORE);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setIssuedAt(const Poco::Timestamp& issuedAt)
|
||||
{
|
||||
setTimestamp(CLAIM_ISSUED_AT, issuedAt);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Timestamp Token::getIssuedAt() const
|
||||
{
|
||||
return getTimestamp(CLAIM_ISSUED_AT);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setId(const std::string& id)
|
||||
{
|
||||
_pPayload->set(CLAIM_JWT_ID, id);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getId() const
|
||||
{
|
||||
return _pPayload->optValue(CLAIM_JWT_ID, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setType(const std::string& type)
|
||||
{
|
||||
_pHeader->set(CLAIM_TYPE, type);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getType() const
|
||||
{
|
||||
return _pHeader->optValue(CLAIM_TYPE, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setAlgorithm(const std::string& algorithm)
|
||||
{
|
||||
_pHeader->set(CLAIM_ALGORITHM, algorithm);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getAlgorithm() const
|
||||
{
|
||||
return _pHeader->optValue(CLAIM_ALGORITHM, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
inline void Token::setContentType(const std::string& contentType)
|
||||
{
|
||||
_pHeader->set(CLAIM_CONTENT_TYPE, contentType);
|
||||
}
|
||||
|
||||
|
||||
inline std::string Token::getContentType() const
|
||||
{
|
||||
return _pHeader->optValue(CLAIM_CONTENT_TYPE, EMPTY);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
||||
|
||||
|
||||
#endif // JWT_Token_INCLUDED
|
35
JWT/src/JWTException.cpp
Normal file
35
JWT/src/JWTException.cpp
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
JWT/src/Serializer.cpp
Normal file
81
JWT/src/Serializer.cpp
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
|
503
JWT/src/Signer.cpp
Normal file
503
JWT/src/Signer.cpp
Normal file
@ -0,0 +1,503 @@
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
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
|
180
JWT/src/Token.cpp
Normal file
180
JWT/src/Token.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
//
|
||||
// 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(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 = (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 = epochSeconds*Poco::Timestamp::resolution();
|
||||
return Poco::Timestamp(tv);
|
||||
}
|
||||
|
||||
|
||||
void Token::sign(const std::string& signature)
|
||||
{
|
||||
_signature = signature;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::JWT
|
27
JWT/testsuite/CMakeLists.txt
Normal file
27
JWT/testsuite/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
# Sources
|
||||
file(GLOB SRCS_G "src/*.cpp")
|
||||
POCO_SOURCES_AUTO( TEST_SRCS ${SRCS_G})
|
||||
|
||||
# Headers
|
||||
file(GLOB_RECURSE HDRS_G "src/*.h" )
|
||||
POCO_HEADERS_AUTO( TEST_SRCS ${HDRS_G})
|
||||
|
||||
POCO_SOURCES_AUTO_PLAT( TEST_SRCS OFF
|
||||
src/WinDriver.cpp
|
||||
)
|
||||
|
||||
POCO_SOURCES_AUTO_PLAT( TEST_SRCS WINCE
|
||||
src/WinCEDriver.cpp
|
||||
)
|
||||
|
||||
add_executable(JWT-testrunner ${TEST_SRCS} )
|
||||
if(ANDROID)
|
||||
add_test(NAME JWT WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
COMMAND ${CMAKE_COMMAND} -DANDROID_NDK=${ANDROID_NDK} -DLIBRARY_DIR=${CMAKE_BINARY_DIR}/lib -DUNITTEST=${CMAKE_BINARY_DIR}/bin/JWT-testrunner -DTEST_PARAMETER=-all -P ${CMAKE_SOURCE_DIR}/cmake/ExecuteOnAndroid.cmake)
|
||||
else()
|
||||
add_test(NAME JWT WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND JWT-testrunner -all)
|
||||
endif()
|
||||
target_link_libraries(JWT-testrunner PUBLIC Poco::JWT Poco::Crypto CppUnit)
|
||||
if(UNIX AND NOT ANDROID)
|
||||
target_link_libraries(JWT-testrunner PUBLIC pthread)
|
||||
endif(UNIX AND NOT ANDROID)
|
19
JWT/testsuite/Makefile
Normal file
19
JWT/testsuite/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# Makefile for Poco JWT testsuite
|
||||
#
|
||||
|
||||
include $(POCO_BASE)/build/rules/global
|
||||
|
||||
objects = SerializerTest TokenTest SignerTest JWTTestSuite Driver
|
||||
|
||||
target = testrunner
|
||||
target_version = 1
|
||||
target_libs = PocoJWT PocoJSON PocoCrypto PocoFoundation CppUnit
|
||||
|
||||
include $(POCO_BASE)/build/rules/exec
|
||||
|
||||
ifdef POCO_UNBUNDLED
|
||||
SYSLIBS += -lpcre
|
||||
endif
|
17
JWT/testsuite/src/Driver.cpp
Normal file
17
JWT/testsuite/src/Driver.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// Driver.cpp
|
||||
//
|
||||
// Console-based test driver for Poco JWT.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "CppUnit/TestRunner.h"
|
||||
#include "JWTTestSuite.h"
|
||||
|
||||
|
||||
CppUnitMain(JWTTestSuite)
|
26
JWT/testsuite/src/JWTTestSuite.cpp
Normal file
26
JWT/testsuite/src/JWTTestSuite.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// JWTTestSuite.cpp
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "JWTTestSuite.h"
|
||||
#include "SerializerTest.h"
|
||||
#include "TokenTest.h"
|
||||
#include "SignerTest.h"
|
||||
|
||||
|
||||
CppUnit::Test* JWTTestSuite::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("JWTTestSuite");
|
||||
|
||||
pSuite->addTest(SerializerTest::suite());
|
||||
pSuite->addTest(TokenTest::suite());
|
||||
pSuite->addTest(SignerTest::suite());
|
||||
|
||||
return pSuite;
|
||||
}
|
27
JWT/testsuite/src/JWTTestSuite.h
Normal file
27
JWT/testsuite/src/JWTTestSuite.h
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// JWTTestSuite.h
|
||||
//
|
||||
// Definition of the JWTTestSuite class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef JWTTestSuite_INCLUDED
|
||||
#define JWTTestSuite_INCLUDED
|
||||
|
||||
|
||||
#include "CppUnit/TestSuite.h"
|
||||
|
||||
|
||||
class JWTTestSuite
|
||||
{
|
||||
public:
|
||||
static CppUnit::Test* suite();
|
||||
};
|
||||
|
||||
|
||||
#endif // JWTTestSuite_INCLUDED
|
131
JWT/testsuite/src/SerializerTest.cpp
Normal file
131
JWT/testsuite/src/SerializerTest.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
//
|
||||
// SerializerTest.cpp
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "SerializerTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/JWT/Serializer.h"
|
||||
|
||||
|
||||
using namespace Poco::JWT;
|
||||
|
||||
|
||||
SerializerTest::SerializerTest(const std::string& name):
|
||||
CppUnit::TestCase("SerializerTest")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SerializerTest::~SerializerTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testSerializeEmpty()
|
||||
{
|
||||
Poco::JSON::Object::Ptr pObject = new Poco::JSON::Object;
|
||||
std::string str = Serializer::serialize(*pObject);
|
||||
assert (str == "e30");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testSerializeAlgNone()
|
||||
{
|
||||
Poco::JSON::Object::Ptr pObject = new Poco::JSON::Object;
|
||||
pObject->set("alg", std::string("none"));
|
||||
std::string str = Serializer::serialize(*pObject);
|
||||
assert (str == "eyJhbGciOiJub25lIn0");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testSerializeAlgHS256()
|
||||
{
|
||||
Poco::JSON::Object::Ptr pObject = new Poco::JSON::Object;
|
||||
pObject->set("alg", std::string("HS256"));
|
||||
pObject->set("typ", std::string("JWT"));
|
||||
std::string str = Serializer::serialize(*pObject);
|
||||
assert (str == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testDeserializeEmpty()
|
||||
{
|
||||
std::string serialized("e30");
|
||||
Poco::JSON::Object::Ptr pObject = Serializer::deserialize(serialized);
|
||||
assert (pObject->size() == 0);
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testDeserializeAlgNone()
|
||||
{
|
||||
std::string serialized("eyJhbGciOiJub25lIn0");
|
||||
Poco::JSON::Object::Ptr pObject = Serializer::deserialize(serialized);
|
||||
assert (pObject->size() == 1);
|
||||
assert (pObject->getValue<std::string>("alg") == "none");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testDeserializeAlgHS256()
|
||||
{
|
||||
std::string serialized("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
|
||||
Poco::JSON::Object::Ptr pObject = Serializer::deserialize(serialized);
|
||||
assert (pObject->size() == 2);
|
||||
assert (pObject->getValue<std::string>("alg") == "HS256");
|
||||
assert (pObject->getValue<std::string>("typ") == "JWT");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testSplit()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
|
||||
std::vector<std::string> parts = Serializer::split(jwt);
|
||||
assert (parts.size() == 3);
|
||||
assert (parts[0] == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
|
||||
assert (parts[1] == "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ");
|
||||
assert (parts[2] == "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
|
||||
}
|
||||
|
||||
|
||||
void SerializerTest::testSplitEmptySig()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJub25lIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.");
|
||||
std::vector<std::string> parts = Serializer::split(jwt);
|
||||
assert (parts.size() == 3);
|
||||
assert (parts[0] == "eyJhbGciOiJub25lIn0");
|
||||
assert (parts[1] == "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ");
|
||||
assert (parts[2] == "");
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* SerializerTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SerializerTest");
|
||||
|
||||
CppUnit_addTest(pSuite, SerializerTest, testSerializeEmpty);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testSerializeAlgNone);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testSerializeAlgHS256);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testDeserializeEmpty);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testDeserializeAlgNone);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testDeserializeAlgHS256);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testSplit);
|
||||
CppUnit_addTest(pSuite, SerializerTest, testSplitEmptySig);
|
||||
|
||||
return pSuite;
|
||||
}
|
43
JWT/testsuite/src/SerializerTest.h
Normal file
43
JWT/testsuite/src/SerializerTest.h
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// SerializerTest.h
|
||||
//
|
||||
// Definition of the SerializerTest class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SerializerTest_INCLUDED
|
||||
#define SerializerTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class SerializerTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
SerializerTest(const std::string& name);
|
||||
~SerializerTest();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void testSerializeEmpty();
|
||||
void testSerializeAlgNone();
|
||||
void testSerializeAlgHS256();
|
||||
void testDeserializeEmpty();
|
||||
void testDeserializeAlgNone();
|
||||
void testDeserializeAlgHS256();
|
||||
void testSplit();
|
||||
void testSplitEmptySig();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
};
|
||||
|
||||
|
||||
#endif // SerializerTest_INCLUDED
|
466
JWT/testsuite/src/SignerTest.cpp
Normal file
466
JWT/testsuite/src/SignerTest.cpp
Normal file
@ -0,0 +1,466 @@
|
||||
//
|
||||
// SignerTest.cpp
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "SignerTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/JWT/Signer.h"
|
||||
#include "Poco/JWT/JWTException.h"
|
||||
|
||||
|
||||
using namespace Poco::JWT;
|
||||
|
||||
|
||||
const std::string SignerTest::RSA_PRIVATE_KEY(
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIIEpQIBAAKCAQEAyVsWBblTS6iuhZiScYwX3Q8O0q2rvbC9cw9fO9NE3XMjzSGf\n"
|
||||
"NMMFqRRgnivduUvpXwQxw711Va6Y/7o8xrRJ+LBflKBN7EEMdBbNyj7HvZrrkonW\n"
|
||||
"X/mO1uFo9Tf4Lt0hfomE1tqcXw5IGi4X1wXzvbUvDhFqmFcL3F7alIeSPPoZe5Kq\n"
|
||||
"4PFoVxhH8z+2u4Q3qME2NbYvJqYaaO+cCxX1JtdY230LL/rHXtH+EbhJpHJNGdLz\n"
|
||||
"zCJMdKZF3Aqz4J5lb1z6FYIekzJ20FvJ6it1tCQplQisEJyo2YNYCgzBUeAcJoXw\n"
|
||||
"o4OqsIgfpLWEoTBxm5WbarIwt6yVLRamHGXsZQIDAQABAoIBAQCF5F65gamExu7+\n"
|
||||
"AR1oCcsYgNnPeBKaeXsQlqkyA+NoChdFYVUXZZNPAjDZHLw8aeEOAKEC0unCBu7Q\n"
|
||||
"JcwiKWKCzu1PzGTkc8DPNRa0pJh3WRvKfoOhoDW+Z3c+kHAk4YBTPyipIgcXIk0J\n"
|
||||
"s5rArcGNZXybszMZh9BoQl7Ao4G3rzssIAn4lKhoHPkm4YhJqhboPb0esjTtQXZU\n"
|
||||
"QIbME3Psir2BgtL+dAW15DofmmvSwVFlsW9tM2QMrS7RtEDoDbEgdteAYGJe+BKg\n"
|
||||
"6+wH9fGR7Csacqfg5YWBYBC6zwMtOxYIYLuSA3MeWH529M7V26hog/cntl4CA8C4\n"
|
||||
"Q/vdfjrhAoGBAPzoP7rjkZkwiE49IHLjth7wMEpJJzb9O33jAtRRqz46gXRMO7y2\n"
|
||||
"lADzHkHmMaJThxtVSQleNHWHW/QZosEaVqw8ibfIeUNVnwLZBL02Rp0XyVnLp2zq\n"
|
||||
"bG8kQM5CQO9yrckQ4U7hE6Nb9goXR1DzojdllXjS0G2LuGNeZAjL3Pc5AoGBAMvR\n"
|
||||
"c0UAESCwQX93WyvJRQUsx/3qLWvm84o847W3Ouik4CPxWX6K77lHu8trwl0+sI4r\n"
|
||||
"+1l4IMli1GBYnp+h64kcIHRcdh8cdB2Q0SSovpbIfBQDmLLxH2eZcPsCkimrRvWw\n"
|
||||
"1wdPw3e56vn/uhOil1BBqjTdUel4cJkaQX8bDdKNAoGBALxjfGWIcsJ7xm0RV4R9\n"
|
||||
"XwI4xJ/xUgbCJ3iki00A8OBP0HKC/tSZ5DG458cK49oZAkE4DEmwJL+Pbs2r8vKI\n"
|
||||
"3hs6lROTf9DKjMIgSklvjrYiK9h5vWOCU/eON7/s1lYHRLDLpCmPu4MqU2I86ODC\n"
|
||||
"Owms3+S6lIulUlqiyz1KLnTxAoGBAKYrOjY8Krqi2JOKhNs6+bmRW+/o12VMYqwG\n"
|
||||
"noPNQgrgORk0sQkZTv6YvEPJtCn/bURMGV1FMj3eBFYUiiaNhZFATDlyFJ+ivAxK\n"
|
||||
"wCiKJvCZvYc3s2vYaAk3sUQEQZQVXwH6TiVY430eJ7PwyQ0vFvxIvPLiqeCV3/8C\n"
|
||||
"x/lP3kIVAoGAZbiwceB12RTDCL2jsczN4ZE16VyXvatI44NWtakbuxZoDJGhg5Uu\n"
|
||||
"N2xb6w2mkmaJ0FUi2+B7Vpv8vmH98Aylfev03J4qnJgaNVVEK2nlprkOyflHr7Bj\n"
|
||||
"fIG0bvyvwUNUy8f5idTqcucDi02zu3Sfr2+LocNUJgrbvswMIXUE3v8=\n"
|
||||
"-----END RSA PRIVATE KEY-----\n"
|
||||
);
|
||||
|
||||
|
||||
const std::string SignerTest::RSA_PUBLIC_KEY(
|
||||
"-----BEGIN PUBLIC KEY-----\n"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyVsWBblTS6iuhZiScYwX\n"
|
||||
"3Q8O0q2rvbC9cw9fO9NE3XMjzSGfNMMFqRRgnivduUvpXwQxw711Va6Y/7o8xrRJ\n"
|
||||
"+LBflKBN7EEMdBbNyj7HvZrrkonWX/mO1uFo9Tf4Lt0hfomE1tqcXw5IGi4X1wXz\n"
|
||||
"vbUvDhFqmFcL3F7alIeSPPoZe5Kq4PFoVxhH8z+2u4Q3qME2NbYvJqYaaO+cCxX1\n"
|
||||
"JtdY230LL/rHXtH+EbhJpHJNGdLzzCJMdKZF3Aqz4J5lb1z6FYIekzJ20FvJ6it1\n"
|
||||
"tCQplQisEJyo2YNYCgzBUeAcJoXwo4OqsIgfpLWEoTBxm5WbarIwt6yVLRamHGXs\n"
|
||||
"ZQIDAQAB\n"
|
||||
"-----END PUBLIC KEY-----\n"
|
||||
);
|
||||
|
||||
|
||||
const std::string SignerTest::ECDSA_PRIVATE_KEY(
|
||||
"-----BEGIN PRIVATE KEY-----\n"
|
||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2\n"
|
||||
"OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r\n"
|
||||
"1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G\n"
|
||||
"-----END PRIVATE KEY-----\n"
|
||||
);
|
||||
|
||||
|
||||
const std::string SignerTest::ECDSA_PUBLIC_KEY(
|
||||
"-----BEGIN PUBLIC KEY-----\n"
|
||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9\n"
|
||||
"q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==\n"
|
||||
"-----END PUBLIC KEY-----\n"
|
||||
);
|
||||
|
||||
|
||||
SignerTest::SignerTest(const std::string& name):
|
||||
CppUnit::TestCase("SignerTest")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SignerTest::~SignerTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignHS256()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_HS256);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.qn9G7NwFEOjIh-7hfCUDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignHS384()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_HS384);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.9NsI7ahPhCd3itTewXb0GNZi08fuUHXLx0qeBscteMXJiug1PyQ_teA9v7zLgg1W");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignHS512()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_HS512);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.WG4y8U_bDN4T3Vu3L5Q5C4pqssrH4wqBtdrFLVuS8k-BLycCq8_bjYGgo7BCzVt4DFXs3BFUIJQdWBzuJwXHtg");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyHS256()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.qn9G7NwFEOjIh-7hfCUDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "HS256");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "qn9G7NwFEOjIh-7hfCUDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyHS384()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.9NsI7ahPhCd3itTewXb0GNZi08fuUHXLx0qeBscteMXJiug1PyQ_teA9v7zLgg1W");
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
signer.addAlgorithm(Signer::ALGO_HS384);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "HS384");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "9NsI7ahPhCd3itTewXb0GNZi08fuUHXLx0qeBscteMXJiug1PyQ_teA9v7zLgg1W");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyHS512()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.WG4y8U_bDN4T3Vu3L5Q5C4pqssrH4wqBtdrFLVuS8k-BLycCq8_bjYGgo7BCzVt4DFXs3BFUIJQdWBzuJwXHtg");
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
signer.addAlgorithm(Signer::ALGO_HS512);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "HS512");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "WG4y8U_bDN4T3Vu3L5Q5C4pqssrH4wqBtdrFLVuS8k-BLycCq8_bjYGgo7BCzVt4DFXs3BFUIJQdWBzuJwXHtg");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyFailSignature()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.wn9G7NwFEOjIh-7hfCFDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABCDEF");
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
fail("Verification must fail");
|
||||
}
|
||||
catch (SignatureVerificationException&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyFailKey()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.qn9G7NwFEOjIh-7hfCUDZA1aJeQmf7I7YvzCBcdenGw");
|
||||
|
||||
Signer signer("0123456789ABCDEF0123456789ABFAIL");
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
fail("Verification must fail");
|
||||
}
|
||||
catch (SignatureVerificationException&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignRS256()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
std::istringstream privateKeyStream(RSA_PRIVATE_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(0, &privateKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_RS256);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.a27BSSEBTaQZFA1tVX4IZHgyG5HIXcJVZpbpB5LQ_rPTalJjvhDDuWC1dM0G0tUACrzPtUN4BhSd-dygJsX4b35DnWm_gPUNDI3HMm7Ck52mM_2Y6445B6aa_pPPuFk6AWql8WWLzQqo9kjQh8AmbMw2A9bciA1smEEsHVw4-VX1tEtupbhJsXO2FnwkQNhJF_Pp4nuX282UV_4DtZ9LW3jLoEYFytKrM4fhkNKVMY52Cn0DJA89fQYe7098gduCjzqoGtaoKKDngbADn2h_1P8VLZrZEd4UROEHviVLm_qxHrWY8-tB0L7i_JMXxw1qMKAavWA-WbnNDdXpOn_o2Q");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignRS384()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
std::istringstream privateKeyStream(RSA_PRIVATE_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(0, &privateKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_RS384);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.L-34N4v5kLa94Llz-XakGIwL9M00ERciAzZSqxgGIJ2dw9VrIodfK-U00wZZwSA2UEZWIm-LJ7wQBiuUw8oMl_fYsufT8W6dWiGZQ2c24AjGKwpXmypPKjh5yRnylkK-8ZRC1AJuZDsY8DJE7vse1w2eAE_Jw0XRJ-u_lq9Hgxz58ZonV1YzUdyVPtD3gWdhyjnlzPCH7lQM4copVUFN6mFTZzt4WQ2i1O1qW1cD_F4Jul9_5z5BYe7-bK3DoV79AgfbEewdnc4yatLQWMIAkrc2LM_tFe83ABhFYhM0qIH8nOuk3WKyKwtjh15f3h3Fn-JnriSfcC79v-M5UpEsZg");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignRS512()
|
||||
{
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
std::istringstream privateKeyStream(RSA_PRIVATE_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(0, &privateKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_RS512);
|
||||
|
||||
assert (jwt == "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.XQTBYo2zqxcyUGs0H-74tfBY6l8PxBQK7-IAJ1NgEVIeoMDX3zQJu5BQX2_VhjOESOPqGNN-FtiNLD1G-LCvSV1fxJwIVEilT7CTBs5iNii6Jrpha5YPnzETqBiz1zdnyNh_QVbtdRIv2ORlp_OIYNZJrxiRfOGvm2_Z3htDoqgv_Lm8SZqelOntox96GrV6GaXhpKBbLjBSU-XPkSOcm5VuXDCz8tltJ_d5cKxbFDUtS6FBYNMaLEqIL4-_aJU_Ld5TcPQT7MqWlHHZZufA5zzmfKEEgddco6uzCBLOz3B6E4Z5VZDoweCM5R7hnLiZOlK0kYsFoaDCVcK_TZhDNw");
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyRS256()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.a27BSSEBTaQZFA1tVX4IZHgyG5HIXcJVZpbpB5LQ_rPTalJjvhDDuWC1dM0G0tUACrzPtUN4BhSd-dygJsX4b35DnWm_gPUNDI3HMm7Ck52mM_2Y6445B6aa_pPPuFk6AWql8WWLzQqo9kjQh8AmbMw2A9bciA1smEEsHVw4-VX1tEtupbhJsXO2FnwkQNhJF_Pp4nuX282UV_4DtZ9LW3jLoEYFytKrM4fhkNKVMY52Cn0DJA89fQYe7098gduCjzqoGtaoKKDngbADn2h_1P8VLZrZEd4UROEHviVLm_qxHrWY8-tB0L7i_JMXxw1qMKAavWA-WbnNDdXpOn_o2Q");
|
||||
|
||||
std::istringstream publicKeyStream(RSA_PUBLIC_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(&publicKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
signer.addAlgorithm(Signer::ALGO_RS256);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "RS256");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "a27BSSEBTaQZFA1tVX4IZHgyG5HIXcJVZpbpB5LQ_rPTalJjvhDDuWC1dM0G0tUACrzPtUN4BhSd-dygJsX4b35DnWm_gPUNDI3HMm7Ck52mM_2Y6445B6aa_pPPuFk6AWql8WWLzQqo9kjQh8AmbMw2A9bciA1smEEsHVw4-VX1tEtupbhJsXO2FnwkQNhJF_Pp4nuX282UV_4DtZ9LW3jLoEYFytKrM4fhkNKVMY52Cn0DJA89fQYe7098gduCjzqoGtaoKKDngbADn2h_1P8VLZrZEd4UROEHviVLm_qxHrWY8-tB0L7i_JMXxw1qMKAavWA-WbnNDdXpOn_o2Q");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyRS384()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.L-34N4v5kLa94Llz-XakGIwL9M00ERciAzZSqxgGIJ2dw9VrIodfK-U00wZZwSA2UEZWIm-LJ7wQBiuUw8oMl_fYsufT8W6dWiGZQ2c24AjGKwpXmypPKjh5yRnylkK-8ZRC1AJuZDsY8DJE7vse1w2eAE_Jw0XRJ-u_lq9Hgxz58ZonV1YzUdyVPtD3gWdhyjnlzPCH7lQM4copVUFN6mFTZzt4WQ2i1O1qW1cD_F4Jul9_5z5BYe7-bK3DoV79AgfbEewdnc4yatLQWMIAkrc2LM_tFe83ABhFYhM0qIH8nOuk3WKyKwtjh15f3h3Fn-JnriSfcC79v-M5UpEsZg");
|
||||
|
||||
std::istringstream publicKeyStream(RSA_PUBLIC_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(&publicKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
signer.addAlgorithm(Signer::ALGO_RS384);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "RS384");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "L-34N4v5kLa94Llz-XakGIwL9M00ERciAzZSqxgGIJ2dw9VrIodfK-U00wZZwSA2UEZWIm-LJ7wQBiuUw8oMl_fYsufT8W6dWiGZQ2c24AjGKwpXmypPKjh5yRnylkK-8ZRC1AJuZDsY8DJE7vse1w2eAE_Jw0XRJ-u_lq9Hgxz58ZonV1YzUdyVPtD3gWdhyjnlzPCH7lQM4copVUFN6mFTZzt4WQ2i1O1qW1cD_F4Jul9_5z5BYe7-bK3DoV79AgfbEewdnc4yatLQWMIAkrc2LM_tFe83ABhFYhM0qIH8nOuk3WKyKwtjh15f3h3Fn-JnriSfcC79v-M5UpEsZg");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyRS512()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.XQTBYo2zqxcyUGs0H-74tfBY6l8PxBQK7-IAJ1NgEVIeoMDX3zQJu5BQX2_VhjOESOPqGNN-FtiNLD1G-LCvSV1fxJwIVEilT7CTBs5iNii6Jrpha5YPnzETqBiz1zdnyNh_QVbtdRIv2ORlp_OIYNZJrxiRfOGvm2_Z3htDoqgv_Lm8SZqelOntox96GrV6GaXhpKBbLjBSU-XPkSOcm5VuXDCz8tltJ_d5cKxbFDUtS6FBYNMaLEqIL4-_aJU_Ld5TcPQT7MqWlHHZZufA5zzmfKEEgddco6uzCBLOz3B6E4Z5VZDoweCM5R7hnLiZOlK0kYsFoaDCVcK_TZhDNw");
|
||||
|
||||
std::istringstream publicKeyStream(RSA_PUBLIC_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::RSAKey> pKey = new Poco::Crypto::RSAKey(&publicKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
signer.addAlgorithm(Signer::ALGO_RS512);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "RS512");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "XQTBYo2zqxcyUGs0H-74tfBY6l8PxBQK7-IAJ1NgEVIeoMDX3zQJu5BQX2_VhjOESOPqGNN-FtiNLD1G-LCvSV1fxJwIVEilT7CTBs5iNii6Jrpha5YPnzETqBiz1zdnyNh_QVbtdRIv2ORlp_OIYNZJrxiRfOGvm2_Z3htDoqgv_Lm8SZqelOntox96GrV6GaXhpKBbLjBSU-XPkSOcm5VuXDCz8tltJ_d5cKxbFDUtS6FBYNMaLEqIL4-_aJU_Ld5TcPQT7MqWlHHZZufA5zzmfKEEgddco6uzCBLOz3B6E4Z5VZDoweCM5R7hnLiZOlK0kYsFoaDCVcK_TZhDNw");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testSignVerifyES256()
|
||||
{
|
||||
// Note: ECDSA is a strange beast and does not return a "known" signature.
|
||||
// That's why we do the signing and verification in a single test.
|
||||
|
||||
Token token;
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
std::istringstream privateKeyStream(ECDSA_PRIVATE_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::ECKey> pKey = new Poco::Crypto::ECKey(0, &privateKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
std::string jwt = signer.sign(token, Signer::ALGO_ES256);
|
||||
|
||||
std::istringstream publicKeyStream(ECDSA_PUBLIC_KEY);
|
||||
pKey = new Poco::Crypto::ECKey(&publicKeyStream);
|
||||
|
||||
Signer verifier(pKey);
|
||||
verifier.addAlgorithm(Signer::ALGO_ES256);
|
||||
try
|
||||
{
|
||||
Token token2 = verifier.verify(jwt);
|
||||
assert (token2.getAlgorithm() == "ES256");
|
||||
assert (token2.getType() == "JWT");
|
||||
assert (token2.getSubject() == "1234567890");
|
||||
assert (token2.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token2.payload().getValue<std::string>("name") == "John Doe");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignerTest::testVerifyES256()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.kLfRdCmR-qewMgzhCtqJrXVoagoh7es0yWsn3VunuS51FMBBcxLTKRDfdgHih0os4gvBdLMYkJu61_IQqoIYZw");
|
||||
|
||||
std::istringstream publicKeyStream(ECDSA_PUBLIC_KEY);
|
||||
Poco::SharedPtr<Poco::Crypto::ECKey> pKey = new Poco::Crypto::ECKey(&publicKeyStream);
|
||||
|
||||
Signer signer(pKey);
|
||||
signer.addAlgorithm(Signer::ALGO_ES256);
|
||||
try
|
||||
{
|
||||
Token token = signer.verify(jwt);
|
||||
assert (token.getAlgorithm() == "ES256");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "kLfRdCmR-qewMgzhCtqJrXVoagoh7es0yWsn3VunuS51FMBBcxLTKRDfdgHih0os4gvBdLMYkJu61_IQqoIYZw");
|
||||
}
|
||||
catch (JWTException&)
|
||||
{
|
||||
fail("Verification must succeed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* SignerTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SignerTest");
|
||||
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignHS256);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignHS384);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignHS512);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyHS256);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyHS384);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyHS512);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyFailSignature);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyFailKey);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignRS256);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignRS384);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignRS512);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyRS256);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyRS384);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyRS512);
|
||||
CppUnit_addTest(pSuite, SignerTest, testSignVerifyES256);
|
||||
CppUnit_addTest(pSuite, SignerTest, testVerifyES256);
|
||||
|
||||
return pSuite;
|
||||
}
|
57
JWT/testsuite/src/SignerTest.h
Normal file
57
JWT/testsuite/src/SignerTest.h
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// SignerTest.h
|
||||
//
|
||||
// Definition of the SignerTest class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SignerTest_INCLUDED
|
||||
#define SignerTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class SignerTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
SignerTest(const std::string& name);
|
||||
~SignerTest();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void testSignHS256();
|
||||
void testSignHS384();
|
||||
void testSignHS512();
|
||||
void testVerifyHS256();
|
||||
void testVerifyHS384();
|
||||
void testVerifyHS512();
|
||||
void testVerifyFailSignature();
|
||||
void testVerifyFailKey();
|
||||
void testSignRS256();
|
||||
void testSignRS384();
|
||||
void testSignRS512();
|
||||
void testVerifyRS256();
|
||||
void testVerifyRS384();
|
||||
void testVerifyRS512();
|
||||
void testSignVerifyES256();
|
||||
void testVerifyES256();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
static const std::string RSA_PRIVATE_KEY;
|
||||
static const std::string RSA_PUBLIC_KEY;
|
||||
|
||||
static const std::string ECDSA_PRIVATE_KEY;
|
||||
static const std::string ECDSA_PUBLIC_KEY;
|
||||
};
|
||||
|
||||
|
||||
#endif // SignerTest_INCLUDED
|
127
JWT/testsuite/src/TokenTest.cpp
Normal file
127
JWT/testsuite/src/TokenTest.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// TokenTest.cpp
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "TokenTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/JWT/Token.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Poco::JWT;
|
||||
|
||||
|
||||
TokenTest::TokenTest(const std::string& name):
|
||||
CppUnit::TestCase("TokenTest")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TokenTest::~TokenTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::testParse()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
|
||||
|
||||
Token token(jwt);
|
||||
assert (token.getAlgorithm() == "HS256");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::testParseNoSig()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.");
|
||||
|
||||
Token token(jwt);
|
||||
assert (token.getAlgorithm() == "HS256");
|
||||
assert (token.getType() == "JWT");
|
||||
assert (token.getSubject() == "1234567890");
|
||||
assert (token.getIssuedAt().epochTime() == 1516239022);
|
||||
assert (token.payload().getValue<std::string>("name") == "John Doe");
|
||||
assert (token.signature() == "");
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::testSerialize()
|
||||
{
|
||||
Token token;
|
||||
token.setAlgorithm("HS256");
|
||||
token.setType("JWT");
|
||||
token.setSubject("1234567890");
|
||||
token.payload().set("name", std::string("John Doe"));
|
||||
token.setIssuedAt(Poco::Timestamp::fromEpochTime(1516239022));
|
||||
|
||||
std::string jwt = token.toString();
|
||||
assert (jwt == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMzQ1Njc4OTAifQ.");
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::testAssign()
|
||||
{
|
||||
std::string jwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
|
||||
|
||||
Token token(jwt);
|
||||
Token token2(token);
|
||||
|
||||
assert (token.toString() == token2.toString());
|
||||
}
|
||||
|
||||
|
||||
void TokenTest::testAudience()
|
||||
{
|
||||
Token token;
|
||||
|
||||
token.setAudience("11111");
|
||||
assert (token.payload().getValue<std::string>(Token::CLAIM_AUDIENCE) == "11111");
|
||||
|
||||
std::vector<std::string> audience = token.getAudience();
|
||||
assert (audience.size() == 1);
|
||||
assert (audience[0] == "11111");
|
||||
|
||||
audience.push_back("22222");
|
||||
token.setAudience(audience);
|
||||
|
||||
assert (token.payload().isArray(Token::CLAIM_AUDIENCE));
|
||||
audience = token.getAudience();
|
||||
assert (audience.size() == 2);
|
||||
assert (audience[0] == "11111");
|
||||
assert (audience[1] == "22222");
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* TokenTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TokenTest");
|
||||
|
||||
CppUnit_addTest(pSuite, TokenTest, testParse);
|
||||
CppUnit_addTest(pSuite, TokenTest, testParseNoSig);
|
||||
CppUnit_addTest(pSuite, TokenTest, testSerialize);
|
||||
CppUnit_addTest(pSuite, TokenTest, testAssign);
|
||||
CppUnit_addTest(pSuite, TokenTest, testAudience);
|
||||
|
||||
return pSuite;
|
||||
}
|
40
JWT/testsuite/src/TokenTest.h
Normal file
40
JWT/testsuite/src/TokenTest.h
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// TokenTest.h
|
||||
//
|
||||
// Definition of the TokenTest class.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef TokenTest_INCLUDED
|
||||
#define TokenTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/JWT/JWT.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class TokenTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
TokenTest(const std::string& name);
|
||||
~TokenTest();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void testParse();
|
||||
void testParseNoSig();
|
||||
void testSerialize();
|
||||
void testAssign();
|
||||
void testAudience();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
};
|
||||
|
||||
|
||||
#endif // TokenTest_INCLUDED
|
30
JWT/testsuite/src/WinCEDriver.cpp
Normal file
30
JWT/testsuite/src/WinCEDriver.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// WinCEDriver.cpp
|
||||
//
|
||||
// Console-based test driver for Windows CE.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "CppUnit/TestRunner.h"
|
||||
#include "JWTTestSuite.h"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
char buffer[1024];
|
||||
std::wcstombs(buffer, argv[i], sizeof(buffer));
|
||||
args.push_back(std::string(buffer));
|
||||
}
|
||||
CppUnit::TestRunner runner;
|
||||
runner.addTest("JWTTestSuite", JWTTestSuite::suite());
|
||||
return runner.run(args) ? 0 : 1;
|
||||
}
|
28
JWT/testsuite/src/WinDriver.cpp
Normal file
28
JWT/testsuite/src/WinDriver.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// WinDriver.cpp
|
||||
//
|
||||
// Windows test driver for Poco JWT.
|
||||
//
|
||||
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "WinTestRunner/WinTestRunner.h"
|
||||
#include "JWTTestSuite.h"
|
||||
|
||||
|
||||
class TestDriver: public CppUnit::WinTestRunnerApp
|
||||
{
|
||||
void TestMain()
|
||||
{
|
||||
CppUnit::WinTestRunner runner;
|
||||
runner.addTest(JWTTestSuite::suite());
|
||||
runner.run();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TestDriver theDriver;
|
@ -16,6 +16,7 @@ Data/PostgreSQL
|
||||
Zip
|
||||
PageCompiler
|
||||
PageCompiler/File2Page
|
||||
JWT
|
||||
PDF
|
||||
CppParser
|
||||
MongoDB
|
||||
|
Loading…
Reference in New Issue
Block a user