feat: add guided login and authlib URL setup

This commit is contained in:
Anon 2026-07-26 14:17:59 +02:00
parent 47bc47786a
commit 630a5fabef
10 changed files with 528 additions and 66 deletions

View file

@ -27,6 +27,13 @@ namespace MinecraftClient.Protocol
/// </remarks>
public static class ProtocolHandler
{
public enum AuthlibServerValidationResult
{
Valid,
Unreachable,
InvalidResponse
}
/// <summary>
/// Perform a DNS lookup for a Minecraft Service using the specified domain name
/// </summary>
@ -134,6 +141,37 @@ namespace MinecraftClient.Protocol
}
}
/// <summary>
/// Verifies that an authlib-injector URL is reachable and returns its metadata document.
/// </summary>
public static AuthlibServerValidationResult ValidateAuthlibServer(Uri authServerUri)
{
string result = string.Empty;
int statusCode;
try
{
statusCode = DoHTTPSGet(authServerUri, ref result);
}
catch
{
return AuthlibServerValidationResult.Unreachable;
}
if (statusCode != 200)
return AuthlibServerValidationResult.InvalidResponse;
try
{
return Json.ParseJson(result)?["meta"]?["implementationName"]?.GetStringValue() is { Length: > 0 }
? AuthlibServerValidationResult.Valid
: AuthlibServerValidationResult.InvalidResponse;
}
catch
{
return AuthlibServerValidationResult.InvalidResponse;
}
}
/// <summary>
/// Get a protocol handler for the specified Minecraft version
/// </summary>
@ -714,9 +752,10 @@ namespace MinecraftClient.Protocol
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" +
JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) +
"\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
int code = DoHTTPSPost(Config.Main.General.AuthServer.Host, Config.Main.General.AuthServer.Port,
Config.Main.General.AuthServer.AuthlibInjectorAPIPath + "/authserver/authenticate", json_request,
Config.Main.General.AuthServer.UseHttps, ref result);
if (!Config.Main.General.TryGetAuthServerUri(out Uri? authServerUri))
return LoginResult.OtherError;
int code = DoHTTPSPost(authServerUri, "authserver/authenticate", json_request, ref result);
if (code == 200)
{
if (result.Contains("availableProfiles\":[]}"))
@ -922,7 +961,8 @@ namespace MinecraftClient.Protocol
session.PlayerID = profile.UUID;
session.ID = accessToken;
session.RefreshToken = msaResponse.RefreshToken;
InternalConfig.Account.Login = msaResponse.Email;
if (!string.IsNullOrWhiteSpace(msaResponse.Email))
InternalConfig.Account.Login = msaResponse.Email;
return LoginResult.Success;
}
else
@ -1037,9 +1077,10 @@ namespace MinecraftClient.Protocol
"\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) +
"\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) +
"\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
int code = DoHTTPSPost(Config.Main.General.AuthServer.Host, Config.Main.General.AuthServer.Port,
Config.Main.General.AuthServer.AuthlibInjectorAPIPath + "/authserver/refresh", json_request,
Config.Main.General.AuthServer.UseHttps, ref result);
if (!Config.Main.General.TryGetAuthServerUri(out Uri? authServerUri))
return LoginResult.OtherError;
int code = DoHTTPSPost(authServerUri, "authserver/refresh", json_request, ref result);
if (code == 200)
{
if (result is null)
@ -1093,16 +1134,18 @@ namespace MinecraftClient.Protocol
string result = "";
string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid +
"\",\"serverId\":\"" + serverhash + "\"}";
string host = type == LoginType.yggdrasil
? Config.Main.General.AuthServer.Host
: "sessionserver.mojang.com";
int port = type == LoginType.yggdrasil ? Config.Main.General.AuthServer.Port : 443;
string endpoint = type == LoginType.yggdrasil
? Config.Main.General.AuthServer.AuthlibInjectorAPIPath + "/sessionserver/session/minecraft/join"
: "/session/minecraft/join";
int code;
if (type == LoginType.yggdrasil)
{
if (!Config.Main.General.TryGetAuthServerUri(out Uri? authServerUri))
return false;
bool useHttps = type == LoginType.yggdrasil ? Config.Main.General.AuthServer.UseHttps : true;
int code = DoHTTPSPost(host, port, endpoint, json_request, useHttps, ref result);
code = DoHTTPSPost(authServerUri, "sessionserver/session/minecraft/join", json_request, ref result);
}
else
{
code = DoHTTPSPost("sessionserver.mojang.com", 443, "/session/minecraft/join", json_request, ref result);
}
return (code >= 200 && code < 300);
}
catch
@ -1241,6 +1284,16 @@ namespace MinecraftClient.Protocol
return DoHTTPSRequest(HttpMethod.Get, host, port, path, headers, null, useHttps: true, ref result);
}
private static int DoHTTPSGet(Uri requestUri, ref string result)
{
Dictionary<string, string> headers = new()
{
{ "User-Agent", "MCC/" + Program.Version }
};
return DoHTTPSRequest(HttpMethod.Get, requestUri.Host, requestUri.Port, requestUri.PathAndQuery, headers,
null, requestUri.Scheme == Uri.UriSchemeHttps, ref result);
}
/// <summary>
/// Make a POST request to the specified endpoint of the Mojang API
/// </summary>
@ -1253,6 +1306,13 @@ namespace MinecraftClient.Protocol
private static int DoHTTPSPost(string host, int port, string path, string body, ref string result)
=> DoHTTPSPost(host, port, path, body, useHttps: true, ref result);
private static int DoHTTPSPost(Uri baseUri, string relativePath, string body, ref string result)
{
Uri requestUri = new(baseUri, relativePath);
return DoHTTPSPost(requestUri.Host, requestUri.Port, requestUri.PathAndQuery, body,
requestUri.Scheme == Uri.UriSchemeHttps, ref result);
}
/// <summary>
/// Make a POST request to the specified endpoint of the Mojang API
/// </summary>
@ -1392,4 +1452,4 @@ namespace MinecraftClient.Protocol
return dateTime;
}
}
}
}