Add token validation filter based on token signature and expiration date
- changed login request from GET to POST - implement json body conversion to DTO objects - set `user_id` and `role` attributes for HttpRequest inside filter
This commit is contained in:
@@ -1,23 +1,99 @@
|
||||
#include "UserManager.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <jwt-cpp/jwt.h>
|
||||
#include <jwt-cpp/traits/nlohmann-json/defaults.h>
|
||||
#include "dependency_injection/DependencyContainer.h"
|
||||
#include "models/User.h"
|
||||
#include "services/encryption/PasswordEncryptor.h"
|
||||
|
||||
std::string PUBLIC_KEY{
|
||||
R"(-----BEGIN PUBLIC KEY-----
|
||||
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGlyZf3ilQWS862UM0wPL9t+B/La
|
||||
E4QiLOWULVmiHvtg6ly5erX4LeKX9og0LYgdUyialjPRElutRq1dTEJ4x9kgDkT4
|
||||
o+hwcem+OHKkdbIfGSIdrI1SzWPYq8F9JjL9elPghD8Rul1US+2HWyrJkw3YiAjU
|
||||
gmZ8mUpu5Hkq+LjzAgMBAAE=
|
||||
-----END PUBLIC KEY-----)"
|
||||
};
|
||||
|
||||
std::string PRIVATE_KEY{
|
||||
R"(-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWgIBAAKBgGlyZf3ilQWS862UM0wPL9t+B/LaE4QiLOWULVmiHvtg6ly5erX4
|
||||
LeKX9og0LYgdUyialjPRElutRq1dTEJ4x9kgDkT4o+hwcem+OHKkdbIfGSIdrI1S
|
||||
zWPYq8F9JjL9elPghD8Rul1US+2HWyrJkw3YiAjUgmZ8mUpu5Hkq+LjzAgMBAAEC
|
||||
gYATCsimV5OnxQjiUMAOvTNcRN80mPMrSmynLOIfrKpBpRfNlOU3FVFb+StZH2sV
|
||||
iI4q5/e19cyF5726sv2Bh4Q3Uob6eJZfpcReScUtbhFLhikCSTvWf6g+6ebCBF9m
|
||||
HoXQBvJhthRo+9BSoweZjxNZirxO1DaqbrxIdufpBJL9aQJBAL/iyzb7mQ/oq8/j
|
||||
BcVnPlOBK6R3q5ZcynJTgyLMTldAwTB4WZrUPBWt51WUL7LoZhMtQIGNaqApSwyp
|
||||
ehaRKscCQQCMre5E5QXDvAITYIoGNs1x5qVUzKCYXYIv0hdko21V9GLNaYWLL5ux
|
||||
BAZsvNLBE2DMbl4mJiL198qJItYk0nR1AkAIXjGSgkJYiUME29eiljAHoDhxAa7/
|
||||
7af+eFndqJ85+t7x6C2wLNU59M2D0+SIns3kxDJt8+bUeTiGotVqKoZ9AkAELNFK
|
||||
eCWQpo7FNnNCNfQo8jhr6NrHStcnRivtj7AaAfPAtuYAuHv9Z+os5fm3QzT3PDtN
|
||||
FIqrFByNr1v9ocVVAkAWvQ4q4Mkw8u/zCAuPiK9NJn377nc4bENQkcn6ZJ4dbMgt
|
||||
yV8QswCTqtfaXKyOEs46WNYhEtMahiLPeL7V23Mr
|
||||
-----END RSA PRIVATE KEY-----)"
|
||||
};
|
||||
|
||||
UserManager::UserManager()
|
||||
{
|
||||
m_logger = DependencyContainer::Resolve<spdlog::logger>();
|
||||
m_passwordEncryptor = DependencyContainer::Resolve<PasswordEncryptor>();
|
||||
}
|
||||
|
||||
bool UserManager::validateCredentials(const User& userData, std::string&& rawPassword)
|
||||
{
|
||||
auto hashedPassword = hashPassword(std::move(rawPassword));
|
||||
auto base64Hash = drogon::utils::base64Encode(hashedPassword.data(), hashedPassword.size());
|
||||
return base64Hash == userData.passwordHash;
|
||||
return hashedPassword == userData.passwordHash;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> UserManager::hashPassword(std::string&& rawPassword)
|
||||
bool UserManager::validateRegisterData(const RegisterRequestDto& registerData)
|
||||
{
|
||||
return m_passwordEncryptor->encryptPassword(std::move(rawPassword));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string UserManager::generateToken(const User& userData)
|
||||
{
|
||||
return jwt::create()
|
||||
.set_type("JWT")
|
||||
.set_payload_claim("user_id", jwt::claim(userData.id))
|
||||
.set_payload_claim("role", jwt::claim(userData.role))
|
||||
.set_expires_in(std::chrono::seconds{ 3600 })
|
||||
.sign(jwt::algorithm::rs256{ "", PRIVATE_KEY });
|
||||
}
|
||||
|
||||
std::string UserManager::hashPassword(std::string&& rawPassword)
|
||||
{
|
||||
auto hashData = m_passwordEncryptor->encryptPassword(std::move(rawPassword));
|
||||
return drogon::utils::base64Encode(hashData.data(), hashData.size());
|
||||
}
|
||||
|
||||
bool UserManager::validateToken(const std::string& token)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto decoded = jwt::decode(token);
|
||||
|
||||
auto verifier = jwt::verify()
|
||||
.allow_algorithm(jwt::algorithm::rs256{ PUBLIC_KEY, "" });
|
||||
verifier.verify(decoded);
|
||||
}
|
||||
catch (const jwt::error::token_verification_exception& ex)
|
||||
{
|
||||
m_logger->info("Failed to validate token: {}", ex.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string UserManager::getPayloadFromToken(const std::string& token)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto decoded = jwt::decode(token);
|
||||
return decoded.get_payload();
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user