Merge branch 'simplify-login-sequence'
This commit is contained in:
commit
13f71ddbcc
1 changed files with 16 additions and 39 deletions
|
@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
|
||||||
class PyiCloudService(object):
|
class PyiCloudService(object):
|
||||||
"""
|
"""
|
||||||
A base authentication class for the iCloud service. Handles the
|
A base authentication class for the iCloud service. Handles the
|
||||||
validation and authentication required to access iCloud services.
|
authentication required to access iCloud services.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
from pyicloud import PyiCloudService
|
from pyicloud import PyiCloudService
|
||||||
|
@ -48,7 +48,6 @@ class PyiCloudService(object):
|
||||||
self._setup_endpoint = 'https://setup.icloud.com/setup/ws/1'
|
self._setup_endpoint = 'https://setup.icloud.com/setup/ws/1'
|
||||||
|
|
||||||
self._base_login_url = '%s/login' % self._setup_endpoint
|
self._base_login_url = '%s/login' % self._setup_endpoint
|
||||||
self._base_validate_url = '%s/validate' % self._setup_endpoint
|
|
||||||
|
|
||||||
if cookie_directory:
|
if cookie_directory:
|
||||||
self._cookie_directory = os.path.expanduser(
|
self._cookie_directory = os.path.expanduser(
|
||||||
|
@ -77,64 +76,42 @@ class PyiCloudService(object):
|
||||||
# Most likely a pickled cookiejar from earlier versions
|
# Most likely a pickled cookiejar from earlier versions
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.params = {}
|
self.params = {
|
||||||
|
'clientBuildNumber': '14E45',
|
||||||
|
'clientId': self.client_id,
|
||||||
|
}
|
||||||
|
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
|
|
||||||
def refresh_validate(self):
|
|
||||||
"""
|
|
||||||
Queries the /validate endpoint and fetches two key values we need:
|
|
||||||
1. "dsInfo" is a nested object which contains the "dsid" integer.
|
|
||||||
This object doesn't exist until *after* the login has taken place,
|
|
||||||
the first request will compain about a X-APPLE-WEBAUTH-TOKEN cookie
|
|
||||||
2. "instance" is an int which is used to build the "id" query string.
|
|
||||||
This is, pseudo: sha1(email + "instance") to uppercase.
|
|
||||||
"""
|
|
||||||
req = self.session.get(self._base_validate_url, params=self.params)
|
|
||||||
resp = req.json()
|
|
||||||
if 'dsInfo' in resp:
|
|
||||||
dsid = resp['dsInfo']['dsid']
|
|
||||||
self.params.update({'dsid': dsid})
|
|
||||||
instance = resp.get(
|
|
||||||
'instance',
|
|
||||||
uuid.uuid4().hex.encode('utf-8')
|
|
||||||
)
|
|
||||||
sha = hashlib.sha1(
|
|
||||||
self.user.get('apple_id').encode('utf-8') + instance
|
|
||||||
)
|
|
||||||
self.params.update({'id': sha.hexdigest().upper()})
|
|
||||||
|
|
||||||
self.params.update({
|
|
||||||
'clientBuildNumber': '14E45',
|
|
||||||
'clientId': self.client_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
"""
|
"""
|
||||||
Handles the full authentication steps, validating,
|
Handles authentication, and persists the X-APPLE-WEB-KB cookie so that
|
||||||
authenticating and then validating again.
|
subsequent logins will not cause additional e-mails from Apple.
|
||||||
"""
|
"""
|
||||||
self.refresh_validate()
|
|
||||||
|
|
||||||
data = dict(self.user)
|
data = dict(self.user)
|
||||||
data.update({'id': self.params['id'], 'extended_login': False})
|
|
||||||
|
# We authenticate every time, so "remember me" is not needed
|
||||||
|
data.update({'extended_login': False})
|
||||||
|
|
||||||
req = self.session.post(
|
req = self.session.post(
|
||||||
self._base_login_url,
|
self._base_login_url,
|
||||||
params=self.params,
|
params=self.params,
|
||||||
data=json.dumps(data)
|
data=json.dumps(data)
|
||||||
)
|
)
|
||||||
|
|
||||||
if not req.ok:
|
resp = req.json() if req.ok else {}
|
||||||
|
if 'dsInfo' not in resp:
|
||||||
msg = 'Invalid email/password combination.'
|
msg = 'Invalid email/password combination.'
|
||||||
raise PyiCloudFailedLoginException(msg)
|
raise PyiCloudFailedLoginException(msg)
|
||||||
|
|
||||||
|
self.params.update({'dsid': resp['dsInfo']['dsid']})
|
||||||
|
|
||||||
if not os.path.exists(self._cookie_directory):
|
if not os.path.exists(self._cookie_directory):
|
||||||
os.mkdir(self._cookie_directory)
|
os.mkdir(self._cookie_directory)
|
||||||
self.session.cookies.save()
|
self.session.cookies.save()
|
||||||
|
|
||||||
self.refresh_validate()
|
self.discovery = resp
|
||||||
|
|
||||||
self.discovery = req.json()
|
|
||||||
self.webservices = self.discovery['webservices']
|
self.webservices = self.discovery['webservices']
|
||||||
|
|
||||||
def _get_cookiejar_path(self):
|
def _get_cookiejar_path(self):
|
||||||
|
|
Loading…
Reference in a new issue