2026-03-28 00:52:17 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "AuthModule.h"
|
2026-04-03 04:28:52 -04:00
|
|
|
#include "HttpClient.h"
|
|
|
|
|
#include "StringHelpers.h"
|
|
|
|
|
#include "Common/vendor/nlohmann/json.hpp"
|
|
|
|
|
#include <random>
|
|
|
|
|
|
|
|
|
|
static wstring generateServerId()
|
|
|
|
|
{
|
|
|
|
|
static constexpr wchar_t hex[] = L"0123456789abcdef";
|
|
|
|
|
static std::mt19937 rng(std::random_device{}());
|
|
|
|
|
wstring id(16, L'0');
|
|
|
|
|
for (auto &c : id) c = hex[rng() & 0xF];
|
|
|
|
|
return id;
|
|
|
|
|
}
|
2026-03-28 00:52:17 -04:00
|
|
|
|
|
|
|
|
bool AuthModule::validate(const wstring &uid, const wstring &username)
|
|
|
|
|
{
|
|
|
|
|
return !uid.empty() && !username.empty() && username.length() <= 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AuthModule::extractIdentity(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
|
|
|
|
{
|
|
|
|
|
for (const auto &[key, value] : fields)
|
|
|
|
|
{
|
|
|
|
|
if (key == L"uid") outUid = value;
|
|
|
|
|
else if (key == L"username") outUsername = value;
|
|
|
|
|
}
|
|
|
|
|
return validate(outUid, outUsername);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
SessionAuthModule::SessionAuthModule()
|
2026-03-28 00:52:17 -04:00
|
|
|
{
|
2026-04-03 04:28:52 -04:00
|
|
|
endpoints[L"mojang"] = {L"https://authserver.mojang.com", L"https://sessionserver.mojang.com"};
|
|
|
|
|
endpoints[L"elyby"] = {L"https://authserver.ely.by", L"https://authserver.ely.by"};
|
2026-03-28 00:52:17 -04:00
|
|
|
}
|
|
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
const wchar_t *SessionAuthModule::schemeName() { return L"mcconsoles:session"; }
|
2026-03-28 00:52:17 -04:00
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
vector<wstring> SessionAuthModule::supportedVariations()
|
2026-03-28 00:52:17 -04:00
|
|
|
{
|
2026-04-03 04:28:52 -04:00
|
|
|
return {L"mojang", L"elyby"};
|
2026-03-28 00:52:17 -04:00
|
|
|
}
|
|
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
vector<pair<wstring, wstring>> SessionAuthModule::getSettings(const wstring &variation)
|
2026-03-28 00:52:17 -04:00
|
|
|
{
|
2026-04-03 04:28:52 -04:00
|
|
|
auto it = endpoints.find(variation);
|
|
|
|
|
if (it == endpoints.end()) return {};
|
2026-03-28 00:52:17 -04:00
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
activeSessionEndpoint = it->second.sessionEndpoint;
|
|
|
|
|
activeServerId = generateServerId();
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
{L"authEndpoint", it->second.authEndpoint},
|
|
|
|
|
{L"sessionEndpoint", it->second.sessionEndpoint},
|
|
|
|
|
{L"serverId", activeServerId}
|
|
|
|
|
};
|
2026-03-28 00:52:17 -04:00
|
|
|
}
|
|
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
bool SessionAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
2026-03-28 00:52:17 -04:00
|
|
|
{
|
2026-04-03 04:28:52 -04:00
|
|
|
wstring username;
|
|
|
|
|
for (const auto &[k, v] : fields)
|
|
|
|
|
{
|
|
|
|
|
if (k == L"username") username = v;
|
|
|
|
|
}
|
2026-03-28 00:52:17 -04:00
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
if (username.empty() || activeServerId.empty() || activeSessionEndpoint.empty())
|
|
|
|
|
return false;
|
2026-03-28 00:52:17 -04:00
|
|
|
|
2026-04-03 04:28:52 -04:00
|
|
|
string url = narrowStr(activeSessionEndpoint)
|
|
|
|
|
+ "/session/minecraft/hasJoined?username=" + narrowStr(username)
|
|
|
|
|
+ "&serverId=" + narrowStr(activeServerId);
|
|
|
|
|
|
|
|
|
|
auto response = HttpClient::get(url);
|
|
|
|
|
if (response.statusCode != 200)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto json = nlohmann::json::parse(response.body, nullptr, false);
|
|
|
|
|
if (json.is_discarded())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
string id = json.value("id", "");
|
|
|
|
|
string name = json.value("name", "");
|
|
|
|
|
|
|
|
|
|
if (id.empty() || name.empty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
outUid = convStringToWstring(id);
|
|
|
|
|
outUsername = convStringToWstring(name);
|
|
|
|
|
|
|
|
|
|
return validate(outUid, outUsername);
|
2026-03-28 00:52:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const wchar_t *KeypairOfflineAuthModule::schemeName() { return L"mcconsoles:keypair_offline"; }
|
|
|
|
|
|
|
|
|
|
vector<wstring> KeypairOfflineAuthModule::supportedVariations()
|
|
|
|
|
{
|
|
|
|
|
return {L"rsa2048", L"ed25519"};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<pair<wstring, wstring>> KeypairOfflineAuthModule::getSettings(const wstring &variation)
|
|
|
|
|
{
|
|
|
|
|
return {{L"key_type", variation}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool KeypairOfflineAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
|
|
|
|
{
|
|
|
|
|
return extractIdentity(fields, outUid, outUsername);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const wchar_t *OfflineAuthModule::schemeName() { return L"mcconsoles:offline"; }
|
|
|
|
|
|
|
|
|
|
vector<wstring> OfflineAuthModule::supportedVariations()
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<pair<wstring, wstring>> OfflineAuthModule::getSettings(const wstring &variation)
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool OfflineAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
|
|
|
|
{
|
|
|
|
|
return extractIdentity(fields, outUid, outUsername);
|
|
|
|
|
}
|