#include #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 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; } }