def authenticate(self): if (not self.user.get("apple_id") or self.user.get("apple_id") not in VALID_USERS): raise PyiCloudFailedLoginException( "Invalid email/password combination.", None) if not self.user.get( "password") or self.user.get("password") != "valid_pass": raise PyiCloudFailedLoginException( "Invalid email/password combination.", None) self.params.update({"dsid": "ID"}) self._webservices = { "account": { "url": "account_url", }, "findme": { "url": "findme_url", }, "calendar": { "url": "calendar_url", }, "contacts": { "url": "contacts_url", }, "reminders": { "url": "reminders_url", }, }
def authenticate(self): """ Handles authentication, and persists the X-APPLE-WEB-KB cookie so that subsequent logins will not cause additional e-mails from Apple. """ logger.info("Authenticating as %s", self.user['apple_id']) data = dict(self.user) # We authenticate every time, so "remember me" is not needed data.update({'extended_login': self.extended_login}) try: req = self.session.post(self._base_login_url, params=self.params, data=json.dumps(data)) except PyiCloudAPIResponseError as error: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg, error) resp = req.json() self.params.update({'dsid': resp['dsInfo']['dsid']}) if not os.path.exists(self._cookie_directory): os.mkdir(self._cookie_directory) self.session.cookies.save() logger.debug("Cookies saved to %s", self._get_cookiejar_path()) self.data = resp self.webservices = self.data['webservices'] logger.info("Authentication completed successfully") logger.debug(self.params)
def authenticate(self): """ Handles authentication, and persists the X-APPLE-WEB-KB cookie so that subsequent logins will not cause additional e-mails from Apple. """ data = dict(self.user) # We authenticate every time, so "remember me" is not needed data.update({'extended_login': False}) req = self.session.post( self._base_login_url, params=self.params, data=json.dumps(data) ) resp = req.json() if req.ok else {} if 'dsInfo' not in resp: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg) self.params.update({'dsid': resp['dsInfo']['dsid']}) if not os.path.exists(self._cookie_directory): os.mkdir(self._cookie_directory) self.session.cookies.save() self.discovery = resp self.webservices = self.discovery['webservices']
def authenticate(self): """ Handles authentication, and persists the X-APPLE-WEB-KB cookie so that subsequent logins will not cause additional e-mails from Apple. """ LOGGER.info("Authenticating as %s", self.user["apple_id"]) data = dict(self.user) # We authenticate every time, so "remember me" is not needed data.update({"extended_login": False}) try: req = self.session.post( self._base_login_url, params=self.params, data=json.dumps(data) ) except PyiCloudAPIResponseException as error: msg = "Invalid email/password combination." raise PyiCloudFailedLoginException(msg, error) self.data = req.json() self.params.update({"dsid": self.data["dsInfo"]["dsid"]}) self._webservices = self.data["webservices"] if not path.exists(self._cookie_directory): mkdir(self._cookie_directory) self.session.cookies.save() LOGGER.debug("Cookies saved to %s", self._get_cookiejar_path()) LOGGER.info("Authentication completed successfully") LOGGER.debug(self.params)
def authenticate(self): """ Handles the full authentication steps, validating, authenticating and then validating again. """ self.refresh_validate() # Check if cookies directory exists if not os.path.exists(self._cookie_directory): # If not, create it os.mkdir(self._cookie_directory) cookie = self._get_cookie() if cookie: self.session.cookies = cookie data = dict(self.user) data.update({'id': self.params['id'], 'extended_login': False}) req = self.session.post(self._base_login_url, params=self.params, data=json.dumps(data)) if not req.ok: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg) self._update_cookie(req) self.refresh_validate() self.discovery = req.json() self.webservices = self.discovery['webservices']
async def test_password_update_wrong_password(hass: HomeAssistantType): """Test that during password reauthentication wrong password returns correct error.""" config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test", unique_id=USERNAME) config_entry.add_to_hass(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_REAUTH}, data={ **MOCK_CONFIG, "unique_id": USERNAME }, ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.icloud.config_flow.PyiCloudService.authenticate", side_effect=PyiCloudFailedLoginException(), ): result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_PASSWORD: PASSWORD_2}) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {CONF_PASSWORD: "******"}
def test_iphone_battery_raise_failed_login(self): """test find iphone but raise failed login error.""" m_text = mock.Mock() from melissa.actions.find_iphone import iphone_battery with mock.patch('melissa.actions.find_iphone.PyiCloudService') \ as m_pc_service, \ mock.patch('melissa.actions.find_iphone.tts') as m_tts: m_pc_service.side_effect = PyiCloudFailedLoginException() # run iphone_battery(m_text) # testing m_pc_service.assert_called_once_with(M_USERNAME, M_PASSWORD) m_tts.assert_called_once_with('Invalid Username & Password')
async def test_login_failed(hass: HomeAssistant): """Test when we have errors during login.""" with patch( "homeassistant.components.icloud.config_flow.PyiCloudService.authenticate", side_effect=PyiCloudFailedLoginException(), ): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, data={CONF_USERNAME: USERNAME, CONF_PASSWORD: PASSWORD}, ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {CONF_PASSWORD: "******"}
def authenticate(self): """ Handles authentication, and persists the X-APPLE-WEB-KB cookie so that subsequent logins will not cause additional e-mails from Apple. """ logger.info("Authenticating as %s", self.user['apple_id']) data = dict(self.user) # We authenticate every time, so "remember me" is not needed myICloud = hack.PyiCloudService() sess_token = myICloud.get_session_token(self.user['apple_id'], self.user['password']) self.session.headers = { 'Origin': 'https://www.icloud.com', 'Referer': 'https://www.icloud.com/', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', 'Content-Type': 'application/json', 'Accept': 'application/json, text/javascript, */*; q=0.01' } data = { 'accountCountryCode': "GBR", 'extended_login': False, 'dsWebAuthToken': sess_token } try: req = self.session.post( 'https://setup.icloud.com/setup/ws/1/accountLogin', data=json.dumps(data)) except PyiCloudAPIResponseError as error: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg, error) resp = req.json() self.params.update({'dsid': resp['dsInfo']['dsid']}) if not os.path.exists(self._cookie_directory): os.mkdir(self._cookie_directory) self.session.cookies.save() logger.debug("Cookies saved to %s", self._get_cookiejar_path()) self.data = resp self.webservices = self.data['webservices'] logger.info("Authentication completed successfully") logger.debug(self.params)
async def test_login_failed(hass: HomeAssistantType): """Test when we have errors during login.""" flow = init_config_flow(hass) with patch( "pyicloud.base.PyiCloudService.authenticate", side_effect=PyiCloudFailedLoginException(), ): result = await flow.async_step_user({ CONF_USERNAME: USERNAME, CONF_PASSWORD: PASSWORD }) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {CONF_USERNAME: "******"}
def _authenticate_with_credentials_service(self, service): """Authenticate to a specific service using credentials.""" data = { "appName": service, "apple_id": self.user["accountName"], "password": self.user["password"], } try: self.session.post("%s/accountLogin" % self.SETUP_ENDPOINT, data=json.dumps(data)) self.data = self._validate_token() except PyiCloudAPIResponseException as error: msg = "Invalid email/password combination." raise PyiCloudFailedLoginException(msg, error)
def _authenticate_with_token(self): """Authenticate using session token.""" data = { "accountCountryCode": self.session_data.get("account_country"), "dsWebAuthToken": self.session_data.get("session_token"), "extended_login": True, "trustToken": self.session_data.get("trust_token", ""), } try: req = self.session.post("%s/accountLogin" % self.SETUP_ENDPOINT, data=json.dumps(data)) self.data = req.json() except PyiCloudAPIResponseException as error: msg = "Invalid authentication token." raise PyiCloudFailedLoginException(msg, error)
def authenticate(self): """ Handles the full authentication steps, validating, authenticating and then validating again. """ self.refresh_validate() data = dict(self.user) data.update({'id': self.params['id'], 'extended_login': False}) req = self.session.post(self._base_login_url, params=self.params, data=json.dumps(data)) if not req.ok: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg) self.refresh_validate() self.discovery = req.json() self.webservices = self.discovery['webservices']
def authenticate(self): """ Handles authentication, and persists the X-APPLE-WEB-KB cookie so that subsequent logins will not cause additional e-mails from Apple. """ logger.info("Authenticating as %s", self.user['apple_id']) data = dict(self.user) sess_token = self.get_session_token() data = { 'accountCountryCode': "GBR", 'extended_login': False, 'dsWebAuthToken': sess_token } try: req = self.session.post(self._setup_endpoint + '/accountLogin', data=json.dumps(data)) except PyiCloudAPIResponseError as error: msg = 'Invalid email/password combination.' raise PyiCloudFailedLoginException(msg, error) resp = req.json() self.params.update({'dsid': resp['dsInfo']['dsid']}) if not os.path.exists(self._cookie_directory): os.mkdir(self._cookie_directory) self.session.cookies.save() logger.debug("Cookies saved to %s", self._get_cookiejar_path()) self.data = resp self.webservices = self.data['webservices'] logger.info("Authentication completed successfully") logger.debug(self.params)
def authenticate(self, force_refresh=False, service=None): """ Handles authentication, and persists cookies so that subsequent logins will not cause additional e-mails from Apple. """ login_successful = False if self.session_data.get("session_token") and not force_refresh: LOGGER.debug("Checking session token validity") try: self.data = self._validate_token() login_successful = True except PyiCloudAPIResponseException: LOGGER.debug( "Invalid authentication token, will log in from scratch.") if not login_successful and service is not None: app = self.data["apps"][service] if "canLaunchWithOneFactor" in app and app[ "canLaunchWithOneFactor"]: LOGGER.debug("Authenticating as %s for %s", self.user["accountName"], service) try: self._authenticate_with_credentials_service(service) login_successful = True except Exception: LOGGER.debug( "Could not log into service. Attempting brand new login." ) if not login_successful: LOGGER.debug("Authenticating as %s", self.user["accountName"]) data = dict(self.user) data["rememberMe"] = True data["trustTokens"] = [] if self.session_data.get("trust_token"): data["trustTokens"] = [self.session_data.get("trust_token")] headers = self._get_auth_headers() if self.session_data.get("scnt"): headers["scnt"] = self.session_data.get("scnt") if self.session_data.get("session_id"): headers["X-Apple-ID-Session-Id"] = self.session_data.get( "session_id") try: req = self.session.post( "%s/signin" % self.AUTH_ENDPOINT, params={"isRememberMeEnabled": "true"}, data=json.dumps(data), headers=headers, ) except PyiCloudAPIResponseException as error: msg = "Invalid email/password combination." raise PyiCloudFailedLoginException(msg, error) self._authenticate_with_token() self._webservices = self.data["webservices"] LOGGER.debug("Authentication completed successfully")
def authenticate(self): """ Handles the full authentication steps, validating, authenticating and then validating again. """ self.refresh_validate() ''' # Check if cookies directory exists if not os.path.exists(self._cookie_directory): # If not, create it os.mkdir(self._cookie_directory) cookie = self._get_cookie() if cookie: self.session.cookies = cookie ''' # Check if cookies directory exists if not os.path.exists(self._cookie_directory): # If not, create it os.mkdir(self._cookie_directory) # Set path for cookie file cookiefile = self.user.get('apple_id') cookiefile = os.path.join( self._cookie_directory, ''.join([c for c in cookiefile if match(r'\w', c)])) # Check if cookie file already exists if os.path.isfile(cookiefile): # Get cookie data from file with open(cookiefile, 'rb') as f: webKBCookie = pickle.load(f) self.session.cookies = requests.utils.cookiejar_from_dict( webKBCookie) else: webKBCookie = None data = dict(self.user) data.update({'id': self.params['id'], 'extended_login': False}) try: req = self.session.post(self._base_login_url, params=self.params, data=json.dumps(data)) except PyiCloudAPIResponseError as error: msg = 'API Response Error. Invalid email/passwoprd' #msg = req.json() self.logger.exception(u'PyiCloud Login error:') raise PyiCloudFailedLoginException(msg, error) #content_type = req.headers.get('Content-Type', '').split(';')[0] #json_mimetypes = ['application/json', 'text/json'] if not req.ok: msg = 'Invalid email/password combination.' # msg = req.json() self.logger.debug(u'PyiCloud Req Not OK: msg:' + unicode(req)) raise PyiCloudFailedLoginException(msg) # Glenn added dump and save the Whole Cookie File # with open(cookiefile, 'wb') as f: # pickle.dump(req.cookies,f) # Pull X-APPLE-WEB-KB cookie from cookies NewWebKBCookie = next(({ key: val } for key, val in req.cookies.items() if 'X-APPLE-WEB-KB' in key), None) # GlennNZ Additional - if WebCookie Empty check for underscoring formatting which Apples appears to have changed to ! # NOTE Change from APPLE to X underscore APPLE -- previous X Dash Apple etc. if not NewWebKBCookie: NewWebKBCookie = next(({ key: val } for key, val in req.cookies.items() if 'X_APPLE_WEB_KB' in key), None) if NewWebKBCookie and NewWebKBCookie != webKBCookie: # Save the cookie in a pickle file with open(cookiefile, 'wb') as f: pickle.dump(NewWebKBCookie, f) self.refresh_validate() self.discovery = req.json() self.data = req.json() self.webservices = self.discovery['webservices']