#pragma once #include #include #include #include #include #pragma comment(lib, "wininet.lib") namespace JAuth { struct ResponseData { bool success = false; std::string message; std::string sessionid; std::string key; std::string tier; std::string expires; std::string daysleft; std::string hwid; }; class api { public: std::string name; std::string ownerid; std::string secret; std::string version; std::string url; ResponseData response; api(std::string name, std::string ownerid, std::string version, std::string url, std::string secret = "") : name(name), ownerid(ownerid), version(version), url(url), secret(secret) {} // Safe minimal HWID generator (Volume Serial + Machine hint) static std::string get_hwid() { DWORD serialNum = 0; GetVolumeInformationA("C:\\", NULL, 0, &serialNum, NULL, NULL, NULL, 0); char buf[64]; sprintf_s(buf, "JAUTH-%08X-PC", serialNum); return std::string(buf); } // Initialize connection with JAuth server bool init() { std::stringstream ss; ss << "{\"name\":\"" << escape(name) << "\",\"ownerid\":\"" << escape(ownerid) << "\",\"version\":\"" << escape(version) << "\",\"secret\":\"" << escape(secret) << "\"}"; std::string res = post_request("/init", ss.str()); response.success = (res.find("\"success\":true") != std::string::npos); response.message = extract_json_value(res, "message"); response.sessionid = extract_json_value(res, "sessionid"); return response.success; } // Authenticate license key and lock HWID bool license(const std::string& key) { std::string hwid = get_hwid(); std::stringstream ss; ss << "{\"name\":\"" << escape(name) << "\",\"ownerid\":\"" << escape(ownerid) << "\",\"key\":\"" << escape(key) << "\",\"hwid\":\"" << escape(hwid) << "\",\"sessionid\":\"" << escape(response.sessionid) << "\"}"; std::string res = post_request("/license", ss.str()); response.success = (res.find("\"success\":true") != std::string::npos); response.message = extract_json_value(res, "message"); response.key = key; response.tier = extract_json_value(res, "tier"); response.daysleft = extract_json_value(res, "daysleft"); response.expires = extract_json_value(res, "expires"); response.hwid = hwid; return response.success; } private: static std::string escape(const std::string& s) { std::string out; for (char c : s) { if (c == '"') out += "\\\""; else if (c == '\\') out += "\\\\"; else out += c; } return out; } static std::string extract_json_value(const std::string& json, const std::string& key) { std::string search = "\"" + key + "\":"; size_t pos = json.find(search); if (pos == std::string::npos) return ""; pos += search.length(); while (pos < json.length() && (json[pos] == ' ' || json[pos] == '\"')) pos++; size_t end = pos; while (end < json.length() && json[end] != '\"' && json[end] != ',' && json[end] != '}') end++; return json.substr(pos, end - pos); } std::string post_request(const std::string& endpoint, const std::string& postData) { std::string host = "jauth.site"; std::string path = "/api/v1" + endpoint; INTERNET_PORT port = INTERNET_DEFAULT_HTTPS_PORT; DWORD flags = INTERNET_FLAG_SECURE; // Handle localhost or custom domain if (url.find("localhost") != std::string::npos || url.find("127.0.0.1") != std::string::npos) { host = "127.0.0.1"; port = 3000; flags = 0; } else if (url.find("://") != std::string::npos) { std::string raw = url.substr(url.find("://") + 3); size_t slash = raw.find('/'); if (slash != std::string::npos) { host = raw.substr(0, slash); } else { host = raw; } } HINTERNET hInternet = InternetOpenA("JAuthNativeClient/1.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) return ""; HINTERNET hConnect = InternetConnectA(hInternet, host.c_str(), port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConnect) { InternetCloseHandle(hInternet); return ""; } HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", path.c_str(), NULL, NULL, NULL, flags, 0); if (!hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return ""; } std::string headers = "Content-Type: application/json\r\n"; HttpSendRequestA(hRequest, headers.c_str(), (DWORD)headers.length(), (LPVOID)postData.c_str(), (DWORD)postData.length()); std::string response; char buffer[4096]; DWORD bytesRead = 0; while (InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead > 0) { buffer[bytesRead] = '\0'; response += buffer; } InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return response; } }; }