major refactor: auth v3
This commit is contained in:
parent
8a8b4b2573
commit
179d21d7b6
18 changed files with 376 additions and 166 deletions
|
|
@ -4,6 +4,8 @@
|
|||
#include "StringHelpers.h"
|
||||
#include "Common/vendor/nlohmann/json.hpp"
|
||||
#include <random>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
static wstring generateServerId()
|
||||
{
|
||||
|
|
@ -14,50 +16,96 @@ static wstring generateServerId()
|
|||
return id;
|
||||
}
|
||||
|
||||
SessionAuthModule::SessionAuthModule()
|
||||
static vector<YggdrasilProviderConfig> s_registryProviders;
|
||||
static bool s_registryLoaded = false;
|
||||
|
||||
void YggdrasilRegistry::load()
|
||||
{
|
||||
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"};
|
||||
s_registryProviders.clear();
|
||||
|
||||
std::ifstream file("yggdrasil.json");
|
||||
if (file.is_open())
|
||||
{
|
||||
auto j = nlohmann::json::parse(file, nullptr, false);
|
||||
if (j.is_array())
|
||||
{
|
||||
for (const auto &entry : j)
|
||||
{
|
||||
if (!entry.is_object()) continue;
|
||||
YggdrasilProviderConfig cfg;
|
||||
cfg.name = convStringToWstring(entry.value("name", ""));
|
||||
cfg.displayName = convStringToWstring(entry.value("displayName", ""));
|
||||
cfg.authUrl = entry.value("authUrl", "");
|
||||
cfg.sessionUrl = entry.value("sessionUrl", "");
|
||||
if (!cfg.name.empty() && !cfg.sessionUrl.empty())
|
||||
s_registryProviders.push_back(std::move(cfg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (std::none_of(s_registryProviders.begin(), s_registryProviders.end(),
|
||||
[](const auto &p) { return p.name == L"elyby"; }))
|
||||
s_registryProviders.insert(s_registryProviders.begin(),
|
||||
{L"elyby", L"Ely.by", "https://authserver.ely.by/auth", "https://authserver.ely.by/session"});
|
||||
|
||||
s_registryProviders.push_back(
|
||||
{L"mojang", L"Mojang", "", "https://sessionserver.mojang.com/session/minecraft"});
|
||||
|
||||
s_registryLoaded = true;
|
||||
}
|
||||
|
||||
const vector<YggdrasilProviderConfig> &YggdrasilRegistry::providers()
|
||||
{
|
||||
if (!s_registryLoaded) load();
|
||||
return s_registryProviders;
|
||||
}
|
||||
|
||||
const YggdrasilProviderConfig *YggdrasilRegistry::find(const wstring &name)
|
||||
{
|
||||
for (const auto &p : providers())
|
||||
if (p.name == name) return &p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const YggdrasilProviderConfig &YggdrasilRegistry::defaultProvider()
|
||||
{
|
||||
const auto &list = providers();
|
||||
for (const auto &p : list)
|
||||
if (p.name != L"mojang") return p;
|
||||
return list[0];
|
||||
}
|
||||
|
||||
const wchar_t *SessionAuthModule::schemeName() { return L"mcconsoles:session"; }
|
||||
|
||||
vector<wstring> SessionAuthModule::supportedVariations()
|
||||
{
|
||||
return {L"mojang", L"elyby"};
|
||||
vector<wstring> result;
|
||||
for (const auto &p : YggdrasilRegistry::providers())
|
||||
result.push_back(p.name);
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<pair<wstring, wstring>> SessionAuthModule::getSettings(const wstring &variation)
|
||||
{
|
||||
auto it = endpoints.find(variation);
|
||||
if (it == endpoints.end()) return {};
|
||||
auto *p = YggdrasilRegistry::find(variation);
|
||||
if (!p) return {};
|
||||
|
||||
activeSessionEndpoint = it->second.sessionEndpoint;
|
||||
activeProvider = p;
|
||||
activeServerId = generateServerId();
|
||||
|
||||
return {
|
||||
{L"authEndpoint", it->second.authEndpoint},
|
||||
{L"sessionEndpoint", it->second.sessionEndpoint},
|
||||
{L"joinUrl", convStringToWstring(p->joinUrl())},
|
||||
{L"serverId", activeServerId}
|
||||
};
|
||||
}
|
||||
|
||||
bool SessionAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
||||
bool SessionAuthModule::serverVerify(const YggdrasilProviderConfig &provider, const wstring &username, const wstring &serverId, wstring &outUid, wstring &outUsername)
|
||||
{
|
||||
wstring username;
|
||||
for (const auto &[k, v] : fields)
|
||||
{
|
||||
if (k == L"username") username = v;
|
||||
}
|
||||
|
||||
if (username.empty() || activeServerId.empty() || activeSessionEndpoint.empty())
|
||||
return false;
|
||||
|
||||
string url = narrowStr(activeSessionEndpoint)
|
||||
+ "/session/minecraft/hasJoined?username=" + narrowStr(username)
|
||||
+ "&serverId=" + narrowStr(activeServerId);
|
||||
string url = provider.hasJoinedUrl() + "?username=" + narrowStr(username) + "&serverId=" + narrowStr(serverId);
|
||||
|
||||
app.DebugPrintf("AUTH SERVER [%ls]: hasJoined GET %s\n", provider.name.c_str(), url.c_str());
|
||||
auto response = HttpClient::get(url);
|
||||
app.DebugPrintf("AUTH SERVER [%ls]: hasJoined status=%d\n", provider.name.c_str(), response.statusCode);
|
||||
|
||||
if (response.statusCode != 200)
|
||||
return false;
|
||||
|
||||
|
|
@ -67,12 +115,25 @@ bool SessionAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields,
|
|||
|
||||
string id = json.value("id", "");
|
||||
string name = json.value("name", "");
|
||||
|
||||
if (id.empty() || name.empty())
|
||||
return false;
|
||||
|
||||
outUid = convStringToWstring(id);
|
||||
outUsername = convStringToWstring(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionAuthModule::onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername)
|
||||
{
|
||||
wstring username;
|
||||
for (const auto &[k, v] : fields)
|
||||
if (k == L"username") username = v;
|
||||
|
||||
if (username.empty() || activeServerId.empty() || !activeProvider)
|
||||
return false;
|
||||
|
||||
if (!serverVerify(*activeProvider, username, activeServerId, outUid, outUsername))
|
||||
return false;
|
||||
|
||||
return validate(outUid, outUsername);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue