94 lines
3.0 KiB
C++
94 lines
3.0 KiB
C++
#include "authenticator.h"
|
|
#include <iostream>
|
|
|
|
namespace scar {
|
|
|
|
Authenticator::Authenticator(std::shared_ptr<Database> db, const std::string& jwt_secret)
|
|
: db_(db), jwt_secret_(jwt_secret) {}
|
|
|
|
std::string Authenticator::authenticate(const std::string& username, const std::string& password) {
|
|
std::cout << "Authentication attempt for user: '" << username << "'" << std::endl;
|
|
|
|
// Get user from database
|
|
auto user = db_->getUserByUsername(username);
|
|
if (!user) {
|
|
std::cerr << "Authentication failed: user not found" << std::endl;
|
|
return "";
|
|
}
|
|
|
|
std::cout << "User found in database, username: '" << user->username << "'" << std::endl;
|
|
std::cout << "Stored salt (first 20 chars): " << user->salt.substr(0, 20) << std::endl;
|
|
std::cout << "Stored hash (first 20 chars): " << user->password_hash.substr(0, 20) << std::endl;
|
|
|
|
// Hash the provided password with the stored salt
|
|
std::string password_hash = Argon2Wrapper::hashPassword(password, user->salt);
|
|
|
|
std::cout << "Computed hash (first 20 chars): " << password_hash.substr(0, 20) << std::endl;
|
|
|
|
// Verify against stored hash
|
|
if (password_hash != user->password_hash) {
|
|
std::cerr << "Authentication failed: incorrect password" << std::endl;
|
|
std::cerr << " Expected: " << user->password_hash << std::endl;
|
|
std::cerr << " Got: " << password_hash << std::endl;
|
|
return "";
|
|
}
|
|
|
|
// Generate JWT token
|
|
std::string token = JWT::generate(username, jwt_secret_);
|
|
|
|
// Store token in database
|
|
if (!db_->updateUserToken(username, token)) {
|
|
std::cerr << "Failed to update user token" << std::endl;
|
|
return "";
|
|
}
|
|
|
|
// Update user status and last login
|
|
db_->updateUserStatus(username, UserStatus::ONLINE);
|
|
db_->updateLastLogin(username);
|
|
|
|
std::cout << "User '" << username << "' authenticated successfully" << std::endl;
|
|
return token;
|
|
}
|
|
|
|
std::string Authenticator::verifyToken(const std::string& token) {
|
|
// Verify JWT signature and expiration
|
|
if (!JWT::verify(token, jwt_secret_)) {
|
|
return "";
|
|
}
|
|
|
|
// Extract username
|
|
std::string username = JWT::extractUsername(token);
|
|
if (username.empty()) {
|
|
return "";
|
|
}
|
|
|
|
// Verify token matches database
|
|
std::string db_username = db_->getUsernameByToken(token);
|
|
if (db_username != username) {
|
|
return "";
|
|
}
|
|
|
|
return username;
|
|
}
|
|
|
|
bool Authenticator::createUser(const std::string& username, const std::string& password) {
|
|
// Generate salt
|
|
std::string salt = Argon2Wrapper::generateSalt();
|
|
|
|
// Hash password with salt
|
|
std::string password_hash = Argon2Wrapper::hashPassword(password, salt);
|
|
|
|
// Create user in database
|
|
bool success = db_->createUser(username, password_hash, salt);
|
|
|
|
if (success) {
|
|
std::cout << "User '" << username << "' created successfully" << std::endl;
|
|
} else {
|
|
std::cerr << "Failed to create user '" << username << "'" << std::endl;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
} // namespace scar
|