diff --git a/PokemonGo/RocketAPI/Client.cs b/PokemonGo/RocketAPI/Client.cs
index e8fe500..138f2d3 100644
--- a/PokemonGo/RocketAPI/Client.cs
+++ b/PokemonGo/RocketAPI/Client.cs
@@ -20,6 +20,7 @@ using PokemonGo.RocketAPI.GeneratedCode;
using PokemonGo.RocketAPI.Helpers;
using PokemonGo.RocketAPI.Extensions;
using System.Threading;
+using PokemonGo.RocketAPI.Login;
namespace PokemonGo.RocketAPI
{
@@ -46,7 +47,7 @@ namespace PokemonGo.RocketAPI
};
_httpClient = new HttpClient(new RetryHandler(handler));
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Niantic App");
- //"Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G900F Build/LMY48G)");
+ //"Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G900F Build/LMY48G)");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Connection", "keep-alive");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "*/*");
@@ -60,155 +61,22 @@ namespace PokemonGo.RocketAPI
_currentLng = lng;
}
- public async Task LoginGoogle(string deviceId, string email, string refreshToken)
+ public async Task DoGoogleLogin()
{
- var handler = new HttpClientHandler()
+ if (Settings.GoogleRefreshToken == string.Empty)
{
- AutomaticDecompression = DecompressionMethods.GZip,
- AllowAutoRedirect = false
- };
-
- using (var tempHttpClient = new HttpClient(handler))
- {
- tempHttpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent",
- "GoogleAuth/1.4 (kltexx LMY48G); gzip");
- tempHttpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
- tempHttpClient.DefaultRequestHeaders.Add("device", deviceId);
- tempHttpClient.DefaultRequestHeaders.Add("app", "com.nianticlabs.pokemongo");
-
- var response = await tempHttpClient.PostAsync(Resources.GoogleGrantRefreshAccessUrl,
- new FormUrlEncodedContent(
- new[]
- {
- new KeyValuePair<string, string>("androidId", deviceId),
- new KeyValuePair<string, string>("lang", "nl_NL"),
- new KeyValuePair<string, string>("google_play_services_version", "9256238"),
- new KeyValuePair<string, string>("sdk_version", "22"),
- new KeyValuePair<string, string>("device_country", "nl"),
- new KeyValuePair<string, string>("client_sig", Settings.ClientSig),
- new KeyValuePair<string, string>("caller_sig", Settings.ClientSig),
- new KeyValuePair<string, string>("Email", email),
- new KeyValuePair<string, string>("service",
- "audience:server:client_id:848232511240-7so421jotr2609rmqakceuu1luuq0ptb.apps.googleusercontent.com"),
- new KeyValuePair<string, string>("app", "com.nianticlabs.pokemongo"),
- new KeyValuePair<string, string>("check_email", "1"),
- new KeyValuePair<string, string>("token_request_options", ""),
- new KeyValuePair<string, string>("callerPkg", "com.nianticlabs.pokemongo"),
- new KeyValuePair<string, string>("Token", refreshToken)
- }));
-
- var content = await response.Content.ReadAsStringAsync();
- _accessToken = content.Split(new[] {"Auth=", "issueAdvice"}, StringSplitOptions.RemoveEmptyEntries)[0];
- _authType = AuthType.Google;
- }
- }
-
- public async Task LoginGoogle()
- {
-
- String OAUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/device/code";
- String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com";
-
- var handler = new HttpClientHandler()
- {
- AutomaticDecompression = DecompressionMethods.GZip,
- AllowAutoRedirect = false
- };
-
- using (var tempHttpClient = new HttpClient(handler))
- {
- var response = await tempHttpClient.PostAsync(OAUTH_ENDPOINT,
- new FormUrlEncodedContent(
- new[]
- {
- new KeyValuePair<string, string>("client_id", CLIENT_ID),
- new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email")
- }));
-
- var content = await response.Content.ReadAsStringAsync();
- JToken token = JObject.Parse(content);
- JToken token2;
- Console.WriteLine("Please visit " + token.SelectToken("verification_url") + " and enter " + token.SelectToken("user_code"));
- while ((token2 = poll(token)) == null)
- {
- Thread.Sleep(Convert.ToInt32(token.SelectToken("interval")) * 1000);
- }
- string authToken = token2.SelectToken("id_token").ToString();
- Console.WriteLine("Sucessfully receieved token.");
- _accessToken = authToken;
- _authType = AuthType.Google;
- }
- }
-
-
- private JToken poll(JToken json)
- {
- var handler = new HttpClientHandler()
- {
- AutomaticDecompression = DecompressionMethods.GZip,
- AllowAutoRedirect = false
- };
-
- String OAUTH_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token";
- String SECRET = "NCjF1TLi2CcY6t5mt0ZveuL7";
- String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com";
-
- using (var tempHttpClient = new HttpClient(handler))
- {
- var response = tempHttpClient.PostAsync(OAUTH_TOKEN_ENDPOINT,
- new FormUrlEncodedContent(
- new[]
- {
- new KeyValuePair<string, string>("client_id", CLIENT_ID),
- new KeyValuePair<string, string>("client_secret", SECRET),
- new KeyValuePair<string, string>("code", json.SelectToken("device_code").ToString()),
- new KeyValuePair<string, string>("grant_type", "http://oauth.net/grant_type/device/1.0"),
- new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email")
- }));
-
- string content = response.Result.Content.ReadAsStringAsync().Result;
- JToken token = JObject.Parse(content);
- if (token.SelectToken("error") == null)
- {
- return token;
- }
- else
- {
- return null;
- }
+ var tokenResponse = await GoogleLogin.GetAccessToken();
+ _accessToken = tokenResponse.id_token;
+ Settings.GoogleRefreshToken = tokenResponse.access_token;
+ Console.WriteLine($"Put RefreshToken in settings for direct login: {Settings.GoogleRefreshToken}");
}
- }
-
- public async void GoogleLoginByRefreshToken(string refreshToken)
- {
- var handler = new HttpClientHandler() {
- AutomaticDecompression = DecompressionMethods.GZip,
- AllowAutoRedirect = false
- };
-
- using (var tempHttpClient = new HttpClient(handler))
+ else
{
- var response = tempHttpClient.PostAsync("https://www.googleapis.com/oauth2/v4/token",
- new FormUrlEncodedContent(
- new[]
- {
- new KeyValuePair<string, string>("client_id", "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com"),
- new KeyValuePair<string, string>("client_secret", "NCjF1TLi2CcY6t5mt0ZveuL7"),
- new KeyValuePair<string, string>("refresh_token", refreshToken),
- new KeyValuePair<string, string>("grant_type", "refresh_token"),
- new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email")
- }));
-
- var content = await response.Result.Content.ReadAsStringAsync();
-
- JToken token = JObject.Parse(content);
- string authToken = token.SelectToken("id_token").ToString();
- Console.WriteLine("Sucessfully receieved token.");
- _accessToken = authToken;
- _authType = AuthType.Google;
+ var tokenResponse = await GoogleLogin.GetAccessToken(Settings.GoogleRefreshToken);
+ _accessToken = tokenResponse.id_token;
}
}
-
+
public async Task LoginPtc(string username, string password)
{
//Get session cookie
diff --git a/PokemonGo/RocketAPI/Console/Program.cs b/PokemonGo/RocketAPI/Console/Program.cs
index 4eecbc5..76aded9 100644
--- a/PokemonGo/RocketAPI/Console/Program.cs
+++ b/PokemonGo/RocketAPI/Console/Program.cs
@@ -30,7 +30,7 @@ namespace PokemonGo.RocketAPI.Console
}
else
{
- await client.LoginGoogle(Settings.DeviceId, Settings.Email, Settings.LongDurationToken);
+ await client.DoGoogleLogin();
}
var serverResponse = await client.GetServer();
var profile = await client.GetProfile();
diff --git a/PokemonGo/RocketAPI/Helpers/HttpClientHelper.cs b/PokemonGo/RocketAPI/Helpers/HttpClientHelper.cs
new file mode 100644
index 0000000..f3d8df4
--- /dev/null
+++ b/PokemonGo/RocketAPI/Helpers/HttpClientHelper.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+
+namespace PokemonGo.RocketAPI.Helpers
+{
+ public class HttpClientHelper
+ {
+ public static async Task<TResponse> PostFormEncodedAsync<TResponse>(string url, params KeyValuePair<string, string>[] keyValuePairs)
+ {
+ var handler = new HttpClientHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.GZip,
+ AllowAutoRedirect = false
+ };
+
+ using (var tempHttpClient = new HttpClient(handler))
+ {
+ var response = await tempHttpClient.PostAsync(url, new FormUrlEncodedContent(keyValuePairs));
+ return await response.Content.ReadAsAsync<TResponse>();
+ }
+ }
+ }
+}
diff --git a/PokemonGo/RocketAPI/Login/GoogleLogin.cs b/PokemonGo/RocketAPI/Login/GoogleLogin.cs
new file mode 100644
index 0000000..05f412d
--- /dev/null
+++ b/PokemonGo/RocketAPI/Login/GoogleLogin.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using PokemonGo.RocketAPI.Enums;
+using PokemonGo.RocketAPI.Helpers;
+
+namespace PokemonGo.RocketAPI.Login
+{
+ internal static class GoogleLogin
+ {
+ private const string OauthTokenEndpoint = "https://www.googleapis.com/oauth2/v4/token";
+ private const string OauthEndpoint = "https://accounts.google.com/o/oauth2/device/code";
+ private const string ClientId = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com";
+ private const string ClientSecret = "NCjF1TLi2CcY6t5mt0ZveuL7";
+
+ internal static async Task<TokenResponseModel> GetAccessToken()
+ {
+ var deviceCodeResponse = await GetDeviceCode();
+ Console.WriteLine("Please visit " + deviceCodeResponse.verification_url + " and enter " + deviceCodeResponse.user_code);
+
+ //Poll until user submitted code..
+ TokenResponseModel tokenResponse;
+ do
+ {
+ await Task.Delay(2000);
+ tokenResponse = await PollSubmittedToken(deviceCodeResponse.device_code);
+ } while (tokenResponse.access_token == null || tokenResponse.refresh_token == null);
+
+ return tokenResponse;
+ }
+
+ private static async Task<DeviceCodeModel> GetDeviceCode()
+ {
+ return await HttpClientHelper.PostFormEncodedAsync<DeviceCodeModel>(OauthEndpoint,
+ new KeyValuePair<string, string>("client_id", ClientId),
+ new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email"));
+ }
+
+ private static async Task<TokenResponseModel> PollSubmittedToken(string deviceCode)
+ {
+ return await HttpClientHelper.PostFormEncodedAsync<TokenResponseModel>(OauthTokenEndpoint,
+ new KeyValuePair<string, string>("client_id", ClientId),
+ new KeyValuePair<string, string>("client_secret", ClientSecret),
+ new KeyValuePair<string, string>("code", deviceCode),
+ new KeyValuePair<string, string>("grant_type", "http://oauth.net/grant_type/device/1.0"),
+ new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email"));
+ }
+
+ public static async Task<TokenResponseModel> GetAccessToken(string refreshToken)
+ {
+ return await HttpClientHelper.PostFormEncodedAsync<TokenResponseModel>(OauthTokenEndpoint,
+ new KeyValuePair<string, string>("client_id", ClientId),
+ new KeyValuePair<string, string>("client_secret", ClientSecret),
+ new KeyValuePair<string, string>("refresh_token", refreshToken),
+ new KeyValuePair<string, string>("grant_type", "refresh_token"),
+ new KeyValuePair<string, string>("scope", "openid email https://www.googleapis.com/auth/userinfo.email"));
+ }
+
+
+ internal class ErrorResponseModel
+ {
+ public string error { get; set; }
+ public string error_description { get; set; }
+ }
+
+ internal class TokenResponseModel
+ {
+ public string access_token { get; set; }
+ public string token_type { get; set; }
+ public int expires_in { get; set; }
+ public string refresh_token { get; set; }
+ public string id_token { get; set; }
+ }
+
+
+ public class DeviceCodeModel
+ {
+ public string verification_url { get; set; }
+ public int expires_in { get; set; }
+ public int interval { get; set; }
+ public string device_code { get; set; }
+ public string user_code { get; set; }
+ }
+
+ }
+}
diff --git a/PokemonGo/RocketAPI/PokemonGo.RocketAPI.csproj b/PokemonGo/RocketAPI/PokemonGo.RocketAPI.csproj
index f61df95..02cf8f8 100644
--- a/PokemonGo/RocketAPI/PokemonGo.RocketAPI.csproj
+++ b/PokemonGo/RocketAPI/PokemonGo.RocketAPI.csproj
@@ -88,11 +88,13 @@
<Compile Include="GeneratedCode\PlayerUpdateResponse.cs" />
<Compile Include="GeneratedCode\Request.cs" />
<Compile Include="GeneratedCode\SettingsResponse.cs" />
+ <Compile Include="Helpers\HttpClientHelper.cs" />
<Compile Include="Helpers\JsonHelper.cs" />
<Compile Include="Helpers\ProtoHelper.cs" />
<Compile Include="Helpers\RetryHandler.cs" />
<Compile Include="Helpers\S2Helper.cs" />
<Compile Include="Helpers\Utils.cs" />
+ <Compile Include="Login\GoogleLogin.cs" />
<Compile Include="Settings.cs" />
<None Include="app.config" />
<Compile Include="Client.cs" />
diff --git a/PokemonGo/RocketAPI/Settings.cs b/PokemonGo/RocketAPI/Settings.cs
index 87b81db..e01aa12 100644
--- a/PokemonGo/RocketAPI/Settings.cs
+++ b/PokemonGo/RocketAPI/Settings.cs
@@ -9,13 +9,10 @@ namespace PokemonGo.RocketAPI
public static class Settings
{
//Fetch these settings from intercepting the /auth call in headers and body (only needed for google auth)
- public const bool UsePTC = true;
+ public const bool UsePTC = false;
public const string PtcUsername = "User";
public const string PtcPassword = "alligator2";
- public const string DeviceId = "cool-device-id";
- public const string Email = "fake@gmail.com";
- public const string ClientSig = "fake";
- public const string LongDurationToken = "fakeid";
+ public static string GoogleRefreshToken = string.Empty;
public const double DefaultLatitude = 10;
public const double DefaultLongitude = 10;
You may download the files in Public Git.