scar-chat7/server/auth/authenticator.cpp
2025-12-07 12:00:44 -07:00

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