patch: refactor auth handling. seperate each auth method into their own module.

This commit is contained in:
Matthew Toro 2026-04-05 18:04:53 -04:00
parent 7d8163539c
commit a257d7899e
12 changed files with 186 additions and 157 deletions

View file

@ -346,6 +346,7 @@ void AuthFlow::microsoftFlowThread()
state = AuthFlowState::POLLING;
string msAccessToken;
string msRefreshToken;
const string pollBody = "client_id=" + string(MS_CLIENT_ID) + "&device_code=" + deviceCode + "&grant_type=urn:ietf:params:oauth:grant-type:device_code";
for (int attempt = 0; attempt < 180; attempt++)
{
@ -357,7 +358,7 @@ void AuthFlow::microsoftFlowThread()
auto pollResp = HttpClient::post(
"https://login.live.com/oauth20_token.srf",
"client_id=" + string(MS_CLIENT_ID) + "&device_code=" + deviceCode + "&grant_type=urn:ietf:params:oauth:grant-type:device_code",
pollBody,
"application/x-www-form-urlencoded"
);

View file

@ -55,7 +55,8 @@
#endif
#include "DLCTexturePack.h"
#include "..\Minecraft.World\HandshakeManager.h"
#include "..\Minecraft.World\AuthModule.h"
#include "..\Minecraft.World\SessionAuthModule.h"
#include "..\Minecraft.World\OfflineAuthModule.h"
#include "AuthScreen.h"
#ifdef _WINDOWS64

View file

@ -524,7 +524,7 @@ void UIScene_MainMenu::ShowAuthMenu(int iPad, void *pClass)
s_authPad = iPad;
s_authParam = pClass;
static const wchar_t *authOptions[] = { L"Next", L"Use", L"Add", L"Back" };
static const wchar_t *authOptions[] = { L"Next", L"Use", L"Add", L"Remove" };
ShowAuthMessageBox(iPad, L"Authentication", BuildAuthProfileText(),
authOptions, 4, &UIScene_MainMenu::AuthMenuReturned, pClass, true);
}
@ -565,6 +565,16 @@ int UIScene_MainMenu::AuthMenuReturned(LPVOID lpParam, int iPad, const C4JStorag
ShowAuthAddMenu(iPad, lpParam);
break;
}
case C4JStorage::EMessage_ResultFourthOption:
{
if (!profiles.empty())
{
AuthProfileManager::removeSelectedProfile();
if (auto *scene = ui.FindScene(eUIScene_MessageBox))
static_cast<UIScene_MessageBox *>(scene)->updateContent(BuildAuthProfileText());
}
return 0;
}
default:
{
ui.NavigateBack(iPad);

View file

@ -15,7 +15,8 @@
#include "..\Minecraft.World\SharedConstants.h"
#include "Settings.h"
#include "..\Minecraft.World\HandshakeManager.h"
#include "..\Minecraft.World\AuthModule.h"
#include "..\Minecraft.World\SessionAuthModule.h"
#include "..\Minecraft.World\OfflineAuthModule.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "..\Minecraft.Server\ServerLogManager.h"
#include "..\Minecraft.Server\Access\Access.h"

View file

@ -1,18 +1,5 @@
#include "stdafx.h"
#include "AuthModule.h"
#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;
}
bool AuthModule::validate(const wstring &uid, const wstring &username)
{
@ -28,100 +15,3 @@ bool AuthModule::extractIdentity(const vector<pair<wstring, wstring>> &fields, w
}
return validate(outUid, outUsername);
}
SessionAuthModule::SessionAuthModule()
{
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"};
}
const wchar_t *SessionAuthModule::schemeName() { return L"mcconsoles:session"; }
vector<wstring> SessionAuthModule::supportedVariations()
{
return {L"mojang", L"elyby"};
}
vector<pair<wstring, wstring>> SessionAuthModule::getSettings(const wstring &variation)
{
auto it = endpoints.find(variation);
if (it == endpoints.end()) return {};
activeSessionEndpoint = it->second.sessionEndpoint;
activeServerId = generateServerId();
return {
{L"authEndpoint", it->second.authEndpoint},
{L"sessionEndpoint", it->second.sessionEndpoint},
{L"serverId", activeServerId}
};
}
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() || activeSessionEndpoint.empty())
return false;
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);
}
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);
}

View file

@ -4,7 +4,6 @@ using namespace std;
#include <string>
#include <vector>
#include <utility>
#include <unordered_map>
inline string narrowStr(const wstring &w)
{
@ -26,43 +25,3 @@ public:
protected:
bool extractIdentity(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername);
};
class SessionAuthModule : public AuthModule
{
public:
struct EndpointPair {
wstring authEndpoint;
wstring sessionEndpoint;
};
private:
unordered_map<wstring, EndpointPair> endpoints;
wstring activeSessionEndpoint;
wstring activeServerId;
public:
SessionAuthModule();
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};
class KeypairOfflineAuthModule : public AuthModule
{
public:
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};
class OfflineAuthModule : public AuthModule
{
public:
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};

View file

@ -35,8 +35,8 @@ void HandshakeManager::setCredentials(const wstring &token, const wstring &uid,
vector<shared_ptr<AuthPacket>> HandshakeManager::drainPendingPackets()
{
vector<shared_ptr<AuthPacket>> out;
out.swap(pendingPackets);
auto out = std::move(pendingPackets);
pendingPackets.clear();
return out;
}

View file

@ -0,0 +1,36 @@
#include "stdafx.h"
#include "OfflineAuthModule.h"
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);
}

View file

@ -0,0 +1,22 @@
#pragma once
using namespace std;
#include "AuthModule.h"
class KeypairOfflineAuthModule : public AuthModule
{
public:
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};
class OfflineAuthModule : public AuthModule
{
public:
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};

View file

@ -0,0 +1,78 @@
#include "stdafx.h"
#include "SessionAuthModule.h"
#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;
}
SessionAuthModule::SessionAuthModule()
{
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"};
}
const wchar_t *SessionAuthModule::schemeName() { return L"mcconsoles:session"; }
vector<wstring> SessionAuthModule::supportedVariations()
{
return {L"mojang", L"elyby"};
}
vector<pair<wstring, wstring>> SessionAuthModule::getSettings(const wstring &variation)
{
auto it = endpoints.find(variation);
if (it == endpoints.end()) return {};
activeSessionEndpoint = it->second.sessionEndpoint;
activeServerId = generateServerId();
return {
{L"authEndpoint", it->second.authEndpoint},
{L"sessionEndpoint", it->second.sessionEndpoint},
{L"serverId", activeServerId}
};
}
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() || activeSessionEndpoint.empty())
return false;
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);
}

View file

@ -0,0 +1,27 @@
#pragma once
using namespace std;
#include "AuthModule.h"
#include <unordered_map>
class SessionAuthModule : public AuthModule
{
public:
struct EndpointPair {
wstring authEndpoint;
wstring sessionEndpoint;
};
private:
unordered_map<wstring, EndpointPair> endpoints;
wstring activeSessionEndpoint;
wstring activeServerId;
public:
SessionAuthModule();
const wchar_t *schemeName() override;
vector<wstring> supportedVariations() override;
vector<pair<wstring, wstring>> getSettings(const wstring &variation) override;
bool onAuthData(const vector<pair<wstring, wstring>> &fields, wstring &outUid, wstring &outUsername) override;
};

View file

@ -261,6 +261,10 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_NETWORK_PACKET
"${CMAKE_CURRENT_SOURCE_DIR}/AnimatePacket.h"
"${CMAKE_CURRENT_SOURCE_DIR}/AuthModule.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/AuthModule.h"
"${CMAKE_CURRENT_SOURCE_DIR}/SessionAuthModule.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/SessionAuthModule.h"
"${CMAKE_CURRENT_SOURCE_DIR}/OfflineAuthModule.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/OfflineAuthModule.h"
"${CMAKE_CURRENT_SOURCE_DIR}/AuthPackets.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/AuthPackets.h"
"${CMAKE_CURRENT_SOURCE_DIR}/UUID.cpp"