using Newtonsoft.Json; using System; using System.Collections.Specialized; using System.Net; using System.Security.Cryptography; using System.Text; namespace SteamAuth { /// /// Handles logging the user into the mobile Steam website. Necessary to generate OAuth token and session cookies. /// public class UserLogin { public string Username; public string Password; public ulong SteamID; public bool RequiresCaptcha; public string CaptchaGID = null; public string CaptchaText = null; public bool RequiresEmail; public string EmailDomain = null; public string EmailCode = null; public bool Requires2FA; public string TwoFactorCode = null; public SessionData Session = null; public bool LoggedIn = false; private CookieContainer _cookies = new CookieContainer(); public UserLogin(string username, string password) { this.Username = username; this.Password = password; } public LoginResult DoLogin() { var postData = new NameValueCollection(); var cookies = _cookies; string response = null; if (cookies.Count == 0) { //Generate a SessionID cookies.Add(new Cookie("mobileClientVersion", "0 (2.1.3)", "/", ".steamcommunity.com")); cookies.Add(new Cookie("mobileClient", "android", "/", ".steamcommunity.com")); cookies.Add(new Cookie("Steam_Language", "english", "/", ".steamcommunity.com")); NameValueCollection headers = new NameValueCollection(); headers.Add("X-Requested-With", "com.valvesoftware.android.steam.community"); SteamWeb.MobileLoginRequest("https://steamcommunity.com/login?oauth_client_id=DE45CD61&oauth_scope=read_profile%20write_profile%20read_client%20write_client", "GET", null, cookies, headers); } postData.Add("username", this.Username); response = SteamWeb.MobileLoginRequest(APIEndpoints.COMMUNITY_BASE + "/login/getrsakey", "POST", postData, cookies); if (response == null || response.Contains("\nAn error occurred while processing your request.")) return LoginResult.GeneralFailure; var rsaResponse = JsonConvert.DeserializeObject(response); if (!rsaResponse.Success) { return LoginResult.BadRSA; } RNGCryptoServiceProvider secureRandom = new RNGCryptoServiceProvider(); byte[] encryptedPasswordBytes; using (var rsaEncryptor = new RSACryptoServiceProvider()) { var passwordBytes = Encoding.ASCII.GetBytes(this.Password); var rsaParameters = rsaEncryptor.ExportParameters(false); rsaParameters.Exponent = Util.HexStringToByteArray(rsaResponse.Exponent); rsaParameters.Modulus = Util.HexStringToByteArray(rsaResponse.Modulus); rsaEncryptor.ImportParameters(rsaParameters); encryptedPasswordBytes = rsaEncryptor.Encrypt(passwordBytes, false); } string encryptedPassword = Convert.ToBase64String(encryptedPasswordBytes); postData.Clear(); postData.Add("username", this.Username); postData.Add("password", encryptedPassword); postData.Add("twofactorcode", this.TwoFactorCode ?? ""); postData.Add("captchagid", this.RequiresCaptcha ? this.CaptchaGID : "-1"); postData.Add("captcha_text", this.RequiresCaptcha ? this.CaptchaText : ""); postData.Add("emailsteamid", (this.Requires2FA || this.RequiresEmail) ? this.SteamID.ToString() : ""); postData.Add("emailauth", this.RequiresEmail ? this.EmailCode : ""); postData.Add("rsatimestamp", rsaResponse.Timestamp); postData.Add("remember_login", "false"); postData.Add("oauth_client_id", "DE45CD61"); postData.Add("oauth_scope", "read_profile write_profile read_client write_client"); postData.Add("loginfriendlyname", "#login_emailauth_friendlyname_mobile"); postData.Add("donotcache", Util.GetSystemUnixTime().ToString()); response = SteamWeb.MobileLoginRequest(APIEndpoints.COMMUNITY_BASE + "/login/dologin", "POST", postData, cookies); if (response == null) return LoginResult.GeneralFailure; var loginResponse = JsonConvert.DeserializeObject(response); if (loginResponse.Message != null && loginResponse.Message.Contains("Incorrect login")) { return LoginResult.BadCredentials; } if (loginResponse.CaptchaNeeded) { this.RequiresCaptcha = true; this.CaptchaGID = loginResponse.CaptchaGID; return LoginResult.NeedCaptcha; } if (loginResponse.EmailAuthNeeded) { this.RequiresEmail = true; this.SteamID = loginResponse.EmailSteamID; return LoginResult.NeedEmail; } if (loginResponse.TwoFactorNeeded && !loginResponse.Success) { this.Requires2FA = true; return LoginResult.Need2FA; } if (loginResponse.Message != null && loginResponse.Message.Contains("too many login failures")) { return LoginResult.TooManyFailedLogins; } if (loginResponse.OAuthData == null || loginResponse.OAuthData.OAuthToken == null || loginResponse.OAuthData.OAuthToken.Length == 0) { return LoginResult.GeneralFailure; } if (!loginResponse.LoginComplete) { return LoginResult.BadCredentials; } else { var readableCookies = cookies.GetCookies(new Uri("https://steamcommunity.com")); var oAuthData = loginResponse.OAuthData; SessionData session = new SessionData(); session.OAuthToken = oAuthData.OAuthToken; session.SteamID = oAuthData.SteamID; session.SteamLogin = session.SteamID + "%7C%7C" + oAuthData.SteamLogin; session.SteamLoginSecure = session.SteamID + "%7C%7C" + oAuthData.SteamLoginSecure; session.WebCookie = oAuthData.Webcookie; session.SessionID = readableCookies["sessionid"].Value; this.Session = session; this.LoggedIn = true; return LoginResult.LoginOkay; } } private class LoginResponse { [JsonProperty("success")] public bool Success { get; set; } [JsonProperty("login_complete")] public bool LoginComplete { get; set; } [JsonProperty("oauth")] public string OAuthDataString { get; set; } public OAuth OAuthData { get { return OAuthDataString != null ? JsonConvert.DeserializeObject(OAuthDataString) : null; } } [JsonProperty("captcha_needed")] public bool CaptchaNeeded { get; set; } [JsonProperty("captcha_gid")] public string CaptchaGID { get; set; } [JsonProperty("emailsteamid")] public ulong EmailSteamID { get; set; } [JsonProperty("emailauth_needed")] public bool EmailAuthNeeded { get; set; } [JsonProperty("requires_twofactor")] public bool TwoFactorNeeded { get; set; } [JsonProperty("message")] public string Message { get; set; } internal class OAuth { [JsonProperty("steamid")] public ulong SteamID { get; set; } [JsonProperty("oauth_token")] public string OAuthToken { get; set; } [JsonProperty("wgtoken")] public string SteamLogin { get; set; } [JsonProperty("wgtoken_secure")] public string SteamLoginSecure { get; set; } [JsonProperty("webcookie")] public string Webcookie { get; set; } } } private class RSAResponse { [JsonProperty("success")] public bool Success { get; set; } [JsonProperty("publickey_exp")] public string Exponent { get; set; } [JsonProperty("publickey_mod")] public string Modulus { get; set; } [JsonProperty("timestamp")] public string Timestamp { get; set; } [JsonProperty("steamid")] public ulong SteamID { get; set; } } } public enum LoginResult { LoginOkay, GeneralFailure, BadRSA, BadCredentials, NeedCaptcha, Need2FA, NeedEmail, TooManyFailedLogins, } }