Replace PPFT/urlPost HTML scraping with OAuth 2.0 device code flow for 2FA support

- Add Microsoft.RequestDeviceCode() and Microsoft.PollDeviceCodeToken() methods
- Remove XboxLive.PreAuth() and XboxLive.UserLogin() (HTML scraping)
- Remove PreAuthResponse struct, PPFT/urlPost regex patterns
- Update XblAuthenticate to always use "d=" prefix for OAuth tokens
- Update MicrosoftMCCLogin to use device code flow
- Skip password prompting for Microsoft device code method
- Add translation strings for device code prompts
- Update config comments and documentation

Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/e13b31f3-8d76-4240-bb69-a519a145fc6a
This commit is contained in:
copilot-swe-agent[bot] 2026-03-23 15:38:47 +00:00
parent daeec49789
commit 5147fb42df
8 changed files with 176 additions and 154 deletions

View file

@ -776,20 +776,27 @@ namespace MinecraftClient.Protocol
}
/// <summary>
/// Sign-in to Microsoft Account without using browser. Only works if 2FA is disabled.
/// Might not work well in some rare cases.
/// Sign-in to Microsoft Account using OAuth 2.0 device code flow.
/// Supports accounts with 2FA enabled.
/// </summary>
/// <param name="email"></param>
/// <param name="password"></param>
/// <param name="email">Email hint (unused in device code flow, kept for API compatibility)</param>
/// <param name="password">Password (unused in device code flow, kept for API compatibility)</param>
/// <param name="session"></param>
/// <returns></returns>
private static LoginResult MicrosoftMCCLogin(string email, string password, out SessionToken session)
{
try
{
var msaResponse = XboxLive.UserLogin(email, password, XboxLive.PreAuth());
// Remove refresh token for MCC sign method
msaResponse.RefreshToken = string.Empty;
var deviceCode = Microsoft.RequestDeviceCode();
ConsoleIO.WriteLineFormatted(string.Format(Translations.mcc_device_code_prompt, deviceCode.VerificationUri, deviceCode.UserCode));
// Try to open the verification URL in the user's browser
Microsoft.OpenBrowser(deviceCode.VerificationUri);
ConsoleIO.WriteLineFormatted(Translations.mcc_device_code_waiting);
var msaResponse = Microsoft.PollDeviceCodeToken(deviceCode.DeviceCode, deviceCode.ExpiresIn, deviceCode.Interval);
return MicrosoftLogin(msaResponse, out session);
}
catch (Exception e)
@ -801,7 +808,7 @@ namespace MinecraftClient.Protocol
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
}
return LoginResult.WrongPassword; // Might not always be wrong password
return LoginResult.WrongPassword;
}
}