2026-01-22 23:09:34 +01:00

108 lines
3.0 KiB
C++

#include <sodium.h>
#include "login.hpp"
#include "crow/http_response.h"
#include "databasepool.h"
#include "utils.hpp"
#include "SessionHandler.hpp"
namespace login
{
SessionHandler sessionHandler;
std::string hashPassword(const std::string& password)
{
// Allocate storage for the hash
char hash[crypto_pwhash_STRBYTES];
// Hash the password using Argon2id
if (crypto_pwhash_str(
hash,
password.c_str(),
password.size(),
crypto_pwhash_OPSLIMIT_INTERACTIVE,
crypto_pwhash_MEMLIMIT_INTERACTIVE
) != 0) {
CROW_LOG_ERROR << "Out of memory while hashing password!";
return "";
}
return hash;
}
bool verifyHashWithPassword(const std::string& hash, std::string const& password)
{
return crypto_pwhash_str_verify(hash.c_str(), password.c_str(), password.size()) == 0;
}
std::string getSessionId(const crow::request& req) {
auto cookie_header = req.get_header_value("Cookie");
std::string prefix = "session_id=";
auto pos = cookie_header.find(prefix);
if (pos == std::string::npos) return "";
return cookie_header.substr(pos + prefix.size(), 32);
}
bool isLoggedIn(const crow::request& req) {
std::string sessionId = getSessionId(req);
if (sessionId.empty())
return false;
auto userId = sessionHandler.isSessionValid(sessionId);
return userId.has_value();
}
std::optional<std::string> loginUser(const std::string& username, const std::string& password)
{
auto user = getUser(username);
if (user.has_value()) {
if (verifyHashWithPassword(user.value().password_hash, password))
{
return sessionHandler.createSession(user.value().id);
}
}
return {};
}
bool initLogin(crow::SimpleApp& app)
{
if (sodium_init() < 0) {
CROW_LOG_ERROR << "Failed to Init Sodium";
return false;
}
// createUser("lukas", "Trollar4928");
CROW_ROUTE(app, "/login").methods("POST"_method)
([](const crow::request& req) {
auto body = utils::parseBody(req.body);
if (!body.empty())
return crow::response(400, "Invalid JSON");
auto usenameIt = body.find("username");
auto passwordIt = body.find("password");
if(usenameIt == body.end() || passwordIt == body.end())
return crow::response(400, "No username or password in body");
const std::string& username = usenameIt->second;
const std::string& password = passwordIt->second;
// Validate credentials
auto sessionId = loginUser(username, password);
if(!sessionId.has_value())
return crow::response(401, "Invalid credentials");
// Set cookie
crow::response res;
res.code = 200;
res.set_header(
"Set-Cookie",
"session_id=" + sessionId.value() +
"; HttpOnly; Path=/; SameSite=Strict"
// add "; Secure" when using HTTPS
);
res.body = "Logged in";
return res;
});
return true;
}
}