From 2276f8db2cce6e01840a93dc3e89a066c1ba683f Mon Sep 17 00:00:00 2001 From: Domenico Iezzi Date: Wed, 4 Oct 2017 11:32:56 +0200 Subject: [PATCH] Changed login() behaviour Previously, the ac2dm was meant to be saved in the application state, and later used for subsequent logins, along with the gsfId. This is not correct, because the app needs it only for the first login, and then remains unused in the application state. The correct behaviour is to save the gsfId and the authSubToken, and provide only these two values for subsequent logins Signed-off-by: Domenico Iezzi --- README.md | 10 +++++----- gpapi/googleplay.py | 45 ++++++++++++++++++--------------------------- test.py | 7 ++++--- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 744ac90..5190909 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,14 @@ Check the test.py module for a simple example. An important note about login function: ``` -def login(self, email, password, ac2dmToken=None, gsfId=None) +def login(self, email=None, password=None, gsfId=None, authSubToken=None) ``` for first time logins, you should only provide email and password. -The module will take care of retrieving an ac2dm token, registering -"your device" to the google account you supplied, and retrieving -a Google Service Framework ID (which basically is the android ID of a device). +The module will take care of initalizing the api,upload device information +to the google account you supplied, and retrieving +a Google Service Framework ID (which, from now on, will be the android ID of a device). -For the next logins you **should** save the ac2dm master token and the gsfId (androidId), and provide them as parameters to the login function. If you login again with email and password only, this is the equivalent of deleting the google account from you device and re-initalize it every time. +For the next logins you **should** save the gsfId and the authSubToken, and provide them as parameters to the login function. If you login again with email and password only, this is the equivalent of re-initalizing your android device with a google account. # API reversing diff --git a/gpapi/googleplay.py b/gpapi/googleplay.py index 7bb50c0..a9ed7eb 100644 --- a/gpapi/googleplay.py +++ b/gpapi/googleplay.py @@ -51,7 +51,6 @@ class GooglePlayAPI(object): ACCOUNT = "HOSTED_OR_GOOGLE" authSubToken = None - ac2dmToken = None gsfId = None def __init__(self, debug=False): @@ -94,13 +93,6 @@ class GooglePlayAPI(object): if self.debug: print("authSubToken: " + authSubToken) - def setAc2dmToken(self, ac2dmToken): - self.ac2dmToken = ac2dmToken - - # put your auth token in config.py to avoid multiple login requests - if self.debug: - print("ac2dmToken: " + ac2dmToken) - def getDefaultHeaders(self): """Return the default set of request headers, which can later be updated, based on the request type""" @@ -118,7 +110,7 @@ class GooglePlayAPI(object): headers["Authorization"] = "GoogleLogin auth=%s" % self.authSubToken return headers - def checkin(self, email): + def checkin(self, email, ac2dmToken): headers = self.getDefaultHeaders() headers["Content-Type"] = "application/x-protobuffer" @@ -138,7 +130,7 @@ class GooglePlayAPI(object): request2.id = response.androidId request2.securityToken = response.securityToken request2.accountCookie.append("[" + email + "]") - request2.accountCookie.append(self.ac2dmToken) + request2.accountCookie.append(ac2dmToken) stringRequest = request2.SerializeToString() res2 = requests.post(self.CHECKINURL, data=stringRequest, headers=headers, verify=ssl_verify) @@ -163,28 +155,19 @@ class GooglePlayAPI(object): response = googleplay_pb2.ResponseWrapper.FromString(res.content) - def login(self, email, password, ac2dmToken=None, gsfId=None): + def login(self, email=None, password=None, gsfId=None, authSubToken=None): """Login to your Google Account. For first time login you should provide: * email * password - For the following logins you need to provide all parameters (you - should save gsfId and ac2dmToken somewhere""" - encryptedPass = self.encrypt_password(email, password).decode('utf-8') - if (all( [each != None for each in [email, password, ac2dmToken, gsfId]] )): - # this means that we already setup our account, we just need to get - # a token - self.setAc2dmToken(ac2dmToken) - self.gsfId = gsfId - self.getAuthSubToken(email, encryptedPass) - # check if token is valid with a simple search - self.search('firefox', 1, None) - else: + For the following logins you need to provide: + * gsfId + * authSubToken""" + if email is not None and password is not None: # First time setup, where we obtain an ac2dm token and # upload device information - if (email is None or password is None): - raise Exception("You should provide both email and pass") + encryptedPass = self.encrypt_password(email, password).decode('utf-8') # AC2DM token params = { "Email": email, @@ -209,19 +192,27 @@ class GooglePlayAPI(object): k, v = d.split("=")[0:2] params[k.strip().lower()] = v.strip() if "auth" in params: - self.setAc2dmToken(params["auth"]) + ac2dmToken = params["auth"] elif "error" in params: raise LoginError("server says: " + params["error"]) else: raise LoginError("Auth token not found.") - self.gsfId = self.checkin(email) + self.gsfId = self.checkin(email, ac2dmToken) if self.debug: print("Google Services Framework Id: %s" % "{0:x}".format(self.gsfId)) self.getAuthSubToken(email, encryptedPass) if self.debug: print("Uploading device configuration") self.uploadDeviceConfig() + elif gsfId is not None and authSubToken is not None: + # no need to initialize API + self.gsfId = gsfId + self.setAuthSubToken(authSubToken) + # check if token is valid with a simple search + self.search('firefox', 1, None) + else: + raise LoginError('Either (email,pass) or (gsfId, authSubToken) is needed') def getAuthSubToken(self, email, passwd): params = { diff --git a/test.py b/test.py index 270792a..a0d2fb6 100644 --- a/test.py +++ b/test.py @@ -6,16 +6,17 @@ EMAIL = "maracaiboez" PASSWD = "fjgozwjmkwyvvutt" testApps = ['com.cpuid.cpu_z'] -server = GooglePlayAPI(True) +server = GooglePlayAPI(debug=True) try: print('\nLogging in with email and password\n') server.login(EMAIL, PASSWD, None, None) - ac2dmToken = server.ac2dmToken gsfId = server.gsfId + authSubToken = server.authSubToken print('\nNow trying secondary login with ac2dm token and gsfId saved\n') - server.login(EMAIL, PASSWD, ac2dmToken, gsfId) + server = GooglePlayAPI(debug=True) + server.login(None, None, gsfId, authSubToken) apps = server.search('telegram', 1, None) print('\nFound those apps:\n')