mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Implement browser sign-in method (#1447)
* Implement browser sign-in method * Handle empty link * Improve * Handle user cancel login
This commit is contained in:
parent
424f514be2
commit
71eb1dca17
6 changed files with 124 additions and 8 deletions
|
|
@ -136,17 +136,22 @@ namespace MinecraftClient
|
|||
}
|
||||
|
||||
//Asking the user to type in missing data such as Username and Password
|
||||
|
||||
bool useBrowser = Settings.AccountType == ProtocolHandler.AccountType.Microsoft && Settings.LoginMethod == "browser";
|
||||
if (Settings.Login == "")
|
||||
{
|
||||
if (useBrowser)
|
||||
ConsoleIO.WriteLine("Press Enter to skip session cache checking and continue sign-in with browser");
|
||||
Console.Write(ConsoleIO.BasicIO ? Translations.Get("mcc.login_basic_io") + "\n" : Translations.Get("mcc.login"));
|
||||
Settings.Login = Console.ReadLine();
|
||||
}
|
||||
if (Settings.Password == "" && (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.Login.ToLower())))
|
||||
if (Settings.Password == ""
|
||||
&& (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.Login.ToLower()))
|
||||
&& !useBrowser)
|
||||
{
|
||||
RequestPassword();
|
||||
}
|
||||
|
||||
|
||||
startupargs = args;
|
||||
InitializeClient();
|
||||
}
|
||||
|
|
@ -209,7 +214,6 @@ namespace MinecraftClient
|
|||
SessionCache.Store(Settings.Login.ToLower(), session);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (result == ProtocolHandler.LoginResult.Success)
|
||||
|
|
@ -315,6 +319,7 @@ namespace MinecraftClient
|
|||
case ProtocolHandler.LoginResult.NotPremium: failureReason = "error.login.premium"; break;
|
||||
case ProtocolHandler.LoginResult.OtherError: failureReason = "error.login.network"; break;
|
||||
case ProtocolHandler.LoginResult.SSLError: failureReason = "error.login.ssl"; break;
|
||||
case ProtocolHandler.LoginResult.UserCancel: failureReason = "error.login.cancel"; break;
|
||||
default: failureReason = "error.login.unknown"; break;
|
||||
}
|
||||
failureMessage += Translations.Get(failureReason);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ namespace MinecraftClient.Protocol
|
|||
private Regex invalidAccount = new Regex("Sign in to", RegexOptions.IgnoreCase);
|
||||
private Regex twoFA = new Regex("Help us protect your account", RegexOptions.IgnoreCase);
|
||||
|
||||
public string SignInUrl { get { return authorize; } }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-authentication
|
||||
/// </summary>
|
||||
|
|
@ -114,7 +116,7 @@ namespace MinecraftClient.Protocol
|
|||
if (twoFA.IsMatch(response.Body))
|
||||
{
|
||||
// TODO: Handle 2FA
|
||||
throw new Exception("2FA enabled but not supported yet. Try to disable it in Microsoft account settings");
|
||||
throw new Exception("2FA enabled but not supported yet. Use browser sign-in method or try to disable 2FA in Microsoft account settings");
|
||||
}
|
||||
else if (invalidAccount.IsMatch(response.Body))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ namespace MinecraftClient.Protocol
|
|||
return Protocol18Forge.ServerForceForge(protocol);
|
||||
}
|
||||
|
||||
public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, InvalidResponse, NullError };
|
||||
public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, InvalidResponse, NullError, UserCancel };
|
||||
public enum AccountType { Mojang, Microsoft };
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -344,7 +344,10 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
if (type == AccountType.Microsoft)
|
||||
{
|
||||
return MicrosoftLogin(user, pass, out session);
|
||||
if (Settings.LoginMethod == "mcc")
|
||||
return MicrosoftMCCLogin(user, pass, out session);
|
||||
else
|
||||
return MicrosoftBrowserLogin(out session);
|
||||
}
|
||||
else if (type == AccountType.Mojang)
|
||||
{
|
||||
|
|
@ -353,6 +356,13 @@ namespace MinecraftClient.Protocol
|
|||
else throw new InvalidOperationException("Account type must be Mojang or Microsoft");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Login using Mojang account. Will be outdated after account migration
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="pass"></param>
|
||||
/// <param name="session"></param>
|
||||
/// <returns></returns>
|
||||
private static LoginResult MojangLogin(string user, string pass, out SessionToken session)
|
||||
{
|
||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||
|
|
@ -432,7 +442,101 @@ namespace MinecraftClient.Protocol
|
|||
}
|
||||
}
|
||||
|
||||
private static LoginResult MicrosoftLogin(string email, string password, out SessionToken session)
|
||||
/// <summary>
|
||||
/// Sign-in to Microsoft Account without using browser. Only works if 2FA is disabled.
|
||||
/// Might not work well in some rare cases.
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <param name="session"></param>
|
||||
/// <returns></returns>
|
||||
private static LoginResult MicrosoftMCCLogin(string email, string password, out SessionToken session)
|
||||
{
|
||||
var ms = new XboxLive();
|
||||
try
|
||||
{
|
||||
var msaResponse = ms.UserLogin(email, password, ms.PreAuth());
|
||||
return MicrosoftLogin(msaResponse, out session);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
||||
if (Settings.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||
}
|
||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sign-in to Microsoft Account by asking user to open sign-in page using browser.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The downside is this require user to copy and paste lengthy content from and to console.
|
||||
/// Sign-in page: 218 chars
|
||||
/// Response URL: around 1500 chars
|
||||
/// </remarks>
|
||||
/// <param name="session"></param>
|
||||
/// <returns></returns>
|
||||
public static LoginResult MicrosoftBrowserLogin(out SessionToken session)
|
||||
{
|
||||
var ms = new XboxLive();
|
||||
string[] askOpenLink =
|
||||
{
|
||||
"Copy the following link to your browser and login to your Microsoft Account",
|
||||
">>>>>>>>>>>>>>>>>>>>>>",
|
||||
"",
|
||||
ms.SignInUrl,
|
||||
"",
|
||||
"<<<<<<<<<<<<<<<<<<<<<<",
|
||||
"NOTICE: Once successfully logged in, you will see a blank page in your web browser.",
|
||||
"Copy the contents of your browser's address bar and paste it below to complete the login process.",
|
||||
};
|
||||
ConsoleIO.WriteLine(string.Join("\n", askOpenLink));
|
||||
string[] parts = { };
|
||||
while (true)
|
||||
{
|
||||
string link = ConsoleIO.ReadLine();
|
||||
if (string.IsNullOrEmpty(link))
|
||||
{
|
||||
session = new SessionToken();
|
||||
return LoginResult.UserCancel;
|
||||
}
|
||||
parts = link.Split('#');
|
||||
if (parts.Length < 2)
|
||||
{
|
||||
ConsoleIO.WriteLine("Invalid link. Please try again.");
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
string hash = parts[1];
|
||||
var dict = Request.ParseQueryString(hash);
|
||||
var msaResponse = new XboxLive.UserLoginResponse()
|
||||
{
|
||||
AccessToken = dict["access_token"],
|
||||
RefreshToken = dict["refresh_token"],
|
||||
ExpiresIn = int.Parse(dict["expires_in"])
|
||||
};
|
||||
try
|
||||
{
|
||||
return MicrosoftLogin(msaResponse, out session);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
||||
if (Settings.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||
}
|
||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||
}
|
||||
}
|
||||
|
||||
private static LoginResult MicrosoftLogin(XboxLive.UserLoginResponse msaResponse, out SessionToken session)
|
||||
{
|
||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||
var ms = new XboxLive();
|
||||
|
|
@ -440,7 +544,6 @@ namespace MinecraftClient.Protocol
|
|||
|
||||
try
|
||||
{
|
||||
var msaResponse = ms.UserLogin(email, password, ms.PreAuth());
|
||||
var xblResponse = ms.XblAuthenticate(msaResponse);
|
||||
var xsts = ms.XSTSAuthenticate(xblResponse); // Might throw even password correct
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ login=
|
|||
password=
|
||||
serverip=
|
||||
type=mojang # Account type. mojang or microsoft
|
||||
method=mcc # Microsoft Account sign-in method. mcc OR browser
|
||||
|
||||
# Advanced settings
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ error.login.network=Network error.
|
|||
error.login.ssl=SSL Error.
|
||||
error.login.unknown=Unknown Error.
|
||||
error.login.ssl_help=§8It appears that you are using Mono to run this program.\nThe first time, you have to import HTTPS certificates using:\nmozroots --import --ask-remove
|
||||
error.login.cancel=User cancelled.
|
||||
error.login_failed=Failed to login to this server.
|
||||
error.join=Failed to join this server.
|
||||
error.connect=Failed to connect to this IP.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ namespace MinecraftClient
|
|||
public static string Username = "";
|
||||
public static string Password = "";
|
||||
public static ProtocolHandler.AccountType AccountType = ProtocolHandler.AccountType.Mojang;
|
||||
public static string LoginMethod = "mcc";
|
||||
public static string ServerIP = "";
|
||||
public static ushort ServerPort = 25565;
|
||||
public static string ServerVersion = "";
|
||||
|
|
@ -277,6 +278,9 @@ namespace MinecraftClient
|
|||
case "type": AccountType = argValue == "mojang"
|
||||
? ProtocolHandler.AccountType.Mojang
|
||||
: ProtocolHandler.AccountType.Microsoft; break;
|
||||
case "method": LoginMethod = argValue.ToLower() == "browser"
|
||||
? "browser"
|
||||
: "mcc"; break;
|
||||
case "serverip": if (!SetServerIP(argValue)) serverAlias = argValue; ; break;
|
||||
case "singlecommand": SingleCommand = argValue; break;
|
||||
case "language": Language = argValue; break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue