Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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']
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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']
Exemplo n.º 5
0
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: "******"}
Exemplo n.º 6
0
 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: "******"}
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
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: "******"}
Exemplo n.º 10
0
    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)
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    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']
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
    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")
Exemplo n.º 15
0
    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']