Fix online-mode server login

Fix session checking on server login as described in issue #451
This commit is contained in:
ORelio 2018-05-23 23:08:17 +02:00
parent 78af234a52
commit a75710b501
2 changed files with 33 additions and 28 deletions

View file

@ -262,6 +262,7 @@ namespace MinecraftClient
case ProtocolHandler.LoginResult.AccountMigrated: failureMessage += "Account migrated, use e-mail as username."; break; case ProtocolHandler.LoginResult.AccountMigrated: failureMessage += "Account migrated, use e-mail as username."; break;
case ProtocolHandler.LoginResult.ServiceUnavailable: failureMessage += "Login servers are unavailable. Please try again later."; break; case ProtocolHandler.LoginResult.ServiceUnavailable: failureMessage += "Login servers are unavailable. Please try again later."; break;
case ProtocolHandler.LoginResult.WrongPassword: failureMessage += "Incorrect password, blacklisted IP or too many logins."; break; case ProtocolHandler.LoginResult.WrongPassword: failureMessage += "Incorrect password, blacklisted IP or too many logins."; break;
case ProtocolHandler.LoginResult.InvalidResponse: failureMessage += "Invalid server response."; break;
case ProtocolHandler.LoginResult.NotPremium: failureMessage += "User not premium."; break; case ProtocolHandler.LoginResult.NotPremium: failureMessage += "User not premium."; break;
case ProtocolHandler.LoginResult.OtherError: failureMessage += "Network error."; break; case ProtocolHandler.LoginResult.OtherError: failureMessage += "Network error."; break;
case ProtocolHandler.LoginResult.SSLError: failureMessage += "SSL Error."; break; case ProtocolHandler.LoginResult.SSLError: failureMessage += "SSL Error."; break;

View file

@ -205,16 +205,14 @@ namespace MinecraftClient.Protocol
} }
} }
public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, NullError }; public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, InvalidResponse, NullError };
/// <summary> /// <summary>
/// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme. /// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme.
/// </summary> /// </summary>
/// <param name="user">Login</param> /// <param name="user">Login</param>
/// <param name="pass">Password</param> /// <param name="pass">Password</param>
/// <param name="accesstoken">Will contain the access token returned by Minecraft.net, if the login is successful</param> /// <param name="session">In case of successful login, will contain session information for multiplayer</param>
/// <param name="clienttoken">Will contain the client token generated before sending to Minecraft.net</param>
/// <param name="uuid">Will contain the player's PlayerID, needed for multiplayer</param>
/// <returns>Returns the status of the login (Success, Failure, etc.)</returns> /// <returns>Returns the status of the login (Success, Failure, etc.)</returns>
public static LoginResult GetLogin(string user, string pass, out SessionToken session) public static LoginResult GetLogin(string user, string pass, out SessionToken session)
{ {
@ -233,13 +231,18 @@ namespace MinecraftClient.Protocol
} }
else else
{ {
string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries); Json.JSONData loginResponse = Json.ParseJson(result);
if (temp.Length >= 2) { session.ID = temp[1].Split('"')[0]; } if (loginResponse.Properties.ContainsKey("accessToken")
temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries); && loginResponse.Properties.ContainsKey("selectedProfile")
if (temp.Length >= 2) { session.PlayerName = temp[1].Split('"')[0]; } && loginResponse.Properties["selectedProfile"].Properties.ContainsKey("id")
temp = result.Split(new string[] { "availableProfiles\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries); && loginResponse.Properties["selectedProfile"].Properties.ContainsKey("name"))
if (temp.Length >= 2) { session.PlayerID = temp[1].Split('"')[0]; } {
return LoginResult.Success; session.ID = loginResponse.Properties["accessToken"].StringValue;
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
return LoginResult.Success;
}
else return LoginResult.InvalidResponse;
} }
} }
else if (code == 403) else if (code == 403)
@ -281,8 +284,7 @@ namespace MinecraftClient.Protocol
/// <summary> /// <summary>
/// Validates whether accessToken must be refreshed /// Validates whether accessToken must be refreshed
/// </summary> /// </summary>
/// <param name="accesstoken">Will contain the cached access token previously returned by Minecraft.net</param> /// <param name="session">Session token to validate</param>
/// <param name="clienttoken">Will contain the cached client token created on login</param>
/// <returns>Returns the status of the token (Valid, Invalid, etc.)</returns> /// <returns>Returns the status of the token (Valid, Invalid, etc.)</returns>
public static LoginResult GetTokenValidation(SessionToken session) public static LoginResult GetTokenValidation(SessionToken session)
{ {
@ -314,13 +316,11 @@ namespace MinecraftClient.Protocol
/// Refreshes invalid token /// Refreshes invalid token
/// </summary> /// </summary>
/// <param name="user">Login</param> /// <param name="user">Login</param>
/// <param name="accesstoken">Will contain the new access token returned by Minecraft.net, if the refresh is successful</param> /// <param name="session">In case of successful token refresh, will contain session information for multiplayer</param>
/// <param name="clienttoken">Will contain the client token generated before sending to Minecraft.net</param>
/// <param name="uuid">Will contain the player's PlayerID, needed for multiplayer</param>
/// <returns>Returns the status of the new token request (Success, Failure, etc.)</returns> /// <returns>Returns the status of the new token request (Success, Failure, etc.)</returns>
public static LoginResult GetNewToken(SessionToken currentsession, out SessionToken newsession) public static LoginResult GetNewToken(SessionToken currentsession, out SessionToken session)
{ {
newsession = new SessionToken(); session = new SessionToken();
try try
{ {
string result = ""; string result = "";
@ -332,16 +332,20 @@ namespace MinecraftClient.Protocol
{ {
return LoginResult.NullError; return LoginResult.NullError;
} }
else { else
string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries); {
if (temp.Length >= 2) { newsession.ID = temp[1].Split('"')[0]; } Json.JSONData loginResponse = Json.ParseJson(result);
temp = result.Split(new string[] { "clientToken\":\"" }, StringSplitOptions.RemoveEmptyEntries); if (loginResponse.Properties.ContainsKey("accessToken")
if (temp.Length >= 2) { newsession.ClientID = temp[1].Split('"')[0]; } && loginResponse.Properties.ContainsKey("selectedProfile")
temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries); && loginResponse.Properties["selectedProfile"].Properties.ContainsKey("id")
if (temp.Length >= 2) { newsession.PlayerName = temp[1].Split('"')[0]; } && loginResponse.Properties["selectedProfile"].Properties.ContainsKey("name"))
temp = result.Split(new string[] { "selectedProfile\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries); {
if (temp.Length >= 2) { newsession.PlayerID = temp[1].Split('"')[0]; } session.ID = loginResponse.Properties["accessToken"].StringValue;
return LoginResult.Success; session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
return LoginResult.Success;
}
else return LoginResult.InvalidResponse;
} }
} }
else if (code == 403 && result.Contains("InvalidToken")) else if (code == 403 && result.Contains("InvalidToken"))