Example #1
0
    def require_auth_captcha(self, query_params, form_text, login_form_data,
                             session):
        """Resolve auth captcha case

        :param query_params: dict: response query params, for example:
        {'s': '0', 'email': 'my@email', 'dif': '1', 'role': 'fast', 'sid': '1'}

        :param form_text: str: raw form html data
        :param login_form_data: dict
        :param session: requests.Session
        :return: :raise VkAuthError:
        """
        logger.info('Captcha is needed')

        action_url = parse_form_action_url(form_text)
        logger.debug('form_url %s', action_url)
        if not action_url:
            raise VkAuthError('Cannot find form action url')

        captcha_url = '%s?s=%s&sid=%s' % (self.CAPTCHA_URI, query_params['s'],
                                          query_params['sid'])
        logger.info('Captcha url %s', captcha_url)

        login_form_data['captcha_sid'] = query_params['sid']
        login_form_data['captcha_key'] = self.get_captcha_key(captcha_url)

        response = session.post(action_url, login_form_data)
        return response
Example #2
0
    def require_phone_number(self, html, session):
        logger.info(
            'Auth requires phone number. You do login from unusual place')

        # Raises VkPageWarningsError in case of warnings
        # NOTE: we check only 'security_check' case on warnings for now
        # in future it might be propagated to other cases as well
        check_html_warnings(html=html)

        # Determine form action url
        action_url = parse_form_action_url(html)

        # Get masked phone from html to make things more clear
        phone_prefix, phone_suffix = parse_masked_phone_number(html)

        if self._phone_number:
            code = self._phone_number[len(phone_prefix):-len(phone_suffix)]
        else:
            prompt = 'Enter missing digits of your phone number (%s****%s): '\
                        % (phone_prefix, phone_suffix)
            code = raw_input(prompt)

        params = parse_url_query_params(action_url, fragment=False)
        auth_data = {
            'code': code,
            'act': 'security_check',
            'hash': params['hash']}
        response = session.post(
            url=self.LOGIN_URL + action_url, data=auth_data)
        logger.debug('require_phone_number resp: %s', response.text)
Example #3
0
    def require_auth_captcha(self, response, query_params, login_form_data,
                             http_session):
        """Resolve auth captcha case

        :param response: http response
        :param query_params: dict: response query params, for example:
        {'s': '0', 'email': 'my@email', 'dif': '1', 'role': 'fast', 'sid': '1'}

        :param login_form_data: dict
        :param http_session: requests.Session
        :return: :raise VkAuthError:
        """
        logger.info('Captcha is needed. Query params: %s', query_params)
        form_text = response.text

        action_url = parse_form_action_url(form_text)
        logger.debug('form action url: %s', action_url)
        if not action_url:
            raise VkAuthError('Cannot find form action url')

        captcha_sid, captcha_url = parse_captcha_html(
            html=response.text, response_url=response.url)
        logger.info('Captcha url %s', captcha_url)

        login_form_data['captcha_sid'] = captcha_sid
        login_form_data['captcha_key'] = self.get_captcha_key(captcha_url)

        response = http_session.post(action_url, login_form_data)
        return response
Example #4
0
    def require_auth_captcha(self, query_params, form_text, login_form_data,
                             session):
        """Resolve auth captcha case

        :param query_params: dict: response query params, for example:
        {'s': '0', 'email': 'my@email', 'dif': '1', 'role': 'fast', 'sid': '1'}

        :param form_text: str: raw form html data
        :param login_form_data: dict
        :param session: requests.Session
        :return: :raise VkAuthError:
        """
        logger.info('Captcha is needed')

        action_url = parse_form_action_url(form_text)
        logger.debug('form_url %s', action_url)
        if not action_url:
            raise VkAuthError('Cannot find form action url')

        captcha_url = '%s?s=%s&sid=%s' % (
            self.CAPTCHA_URI, query_params['s'], query_params['sid'])
        logger.info('Captcha url %s', captcha_url)

        login_form_data['captcha_sid'] = query_params['sid']
        login_form_data['captcha_key'] = self.get_captcha_key(captcha_url)

        response = session.post(action_url, login_form_data)
        return response
Example #5
0
    def require_phone_number(self, html, session):
        logger.info(
            'Auth requires phone number. You do login from unusual place')

        # Raises VkPageWarningsError in case of warnings
        # NOTE: we check only 'security_check' case on warnings for now
        # in future it might be propagated to other cases as well
        check_html_warnings(html=html)

        # Determine form action url
        action_url = parse_form_action_url(html)

        # Get masked phone from html to make things more clear
        phone_prefix, phone_suffix = parse_masked_phone_number(html)

        if self._phone_number:
            code = self._phone_number[len(phone_prefix):-len(phone_suffix)]
        else:
            prompt = 'Enter missing digits of your phone number (%s****%s): '\
                        % (phone_prefix, phone_suffix)
            code = raw_input(prompt)

        params = parse_url_query_params(action_url, fragment=False)
        auth_data = {
            'code': code,
            'act': 'security_check',
            'hash': params['hash']
        }
        response = session.post(url=self.LOGIN_URL + action_url,
                                data=auth_data)
        logger.debug('require_phone_number resp: %s', response.text)
Example #6
0
 def require_sms_code(self, html, session):
     logger.info('User enabled 2 factors authorization. '
                 'Auth check code is needed')
     action_url = parse_form_action_url(html)
     auth_check_code = self.get_sms_code()
     auth_check_data = {
         'code': auth_check_code,
         '_ajax': '1',
         'remember': '1'
     }
     response = session.post(action_url, data=auth_check_data)
     return response
Example #7
0
 def require_sms_code(self, html, session):
     logger.info('User enabled 2 factors authorization. '
                 'Auth check code is needed')
     auth_check_form_action = parse_form_action_url(html)
     auth_check_code = self.get_sms_code()
     auth_check_data = {
         'code': auth_check_code,
         '_ajax': '1',
         'remember': '1'
     }
     response = session.post(auth_check_form_action, data=auth_check_data)
     return response
Example #8
0
 def require_2fa(self, html, session):
     logger.info(
         'User enabled 2 factors authentication. Auth check code is needed '
         '(SMS, Google Authenticator or one-time password generated by vk)')
     action_url = parse_form_action_url(html)
     auth_check_code = self.get_2fa_code()
     auth_check_data = {
         'code': auth_check_code,
         '_ajax': '1',
         'remember': '1'
     }
     url = '/'.join([self.LOGIN_URL + action_url])
     response = session.post(url=url, data=auth_check_data)
     return response
Example #9
0
 def require_2fa(self, html, session):
     logger.info(
         'User enabled 2 factors authentication. Auth check code is needed '
         '(SMS, Google Authenticator or one-time password generated by vk)')
     action_url = parse_form_action_url(html)
     auth_check_code = self.get_2fa_code()
     auth_check_data = {
         'code': auth_check_code,
         '_ajax': '1',
         'remember': '1'
     }
     url = '/'.join([self.LOGIN_URL + action_url])
     response = session.post(url=url, data=auth_check_data)
     return response
Example #10
0
    def do_login(self, http_session):
        """Do vk login

        :param http_session: vk_requests.utils.VerboseHTTPSession: http session
        """

        response = http_session.get(self.LOGIN_URL)
        action_url = parse_form_action_url(response.text)

        # Stop login it action url is not found
        if not action_url:
            logger.debug(response.text)
            raise VkParseError("Can't parse form action url")

        login_form_data = {'email': self._login, 'pass': self._password}
        login_response = http_session.post(action_url, login_form_data)
        logger.debug('Cookies: %s', http_session.cookies)

        response_url_query = parse_url_query_params(login_response.url,
                                                    fragment=False)

        logger.debug('response_url_query: %s', response_url_query)
        act = response_url_query.get('act')

        # Check response url query params firstly
        if 'sid' in response_url_query:
            self.require_auth_captcha(query_params=response_url_query,
                                      form_text=login_response.text,
                                      login_form_data=login_form_data,
                                      http_session=http_session)

        elif act == 'authcheck':
            self.require_2fa(html=login_response.text,
                             http_session=http_session)

        elif act == 'security_check':
            self.require_phone_number(html=login_response.text,
                                      session=http_session)

        session_cookies = ('remixsid' in http_session.cookies, 'remixsid6'
                           in http_session.cookies)
        if any(session_cookies):
            logger.info('VK session is established')
            return True
        else:
            message = 'Authorization error: incorrect password or ' \
                      'authentication code'
            logger.error(message)
            raise VkAuthError(message)
Example #11
0
    def do_login(self, session):
        """Do vk login

        :param session: vk_requests.utils.VerboseHTTPSession: http session
        """

        response = session.get(self.LOGIN_URL)
        action_url = parse_form_action_url(response.text)

        # Stop login it action url is not found
        if not action_url:
            logger.debug(response.text)
            raise VkParseError("Can't parse form action url")

        login_form_data = {'email': self._login, 'pass': self._password}
        login_response = session.post(action_url, login_form_data)
        logger.debug('Cookies: %s', session.cookies)

        response_url_query = parse_url_query_params(
            login_response.url, fragment=False)
        act = response_url_query.get('act')
        logger.debug('response_url_query: %s', response_url_query)

        # Check response url query params firstly
        if 'sid' in response_url_query:
            self.require_auth_captcha(
                query_params=response_url_query,
                form_text=login_response.text,
                login_form_data=login_form_data,
                session=session)

        elif act == 'authcheck':
            self.require_2fa(html=login_response.text, session=session)

        elif act == 'security_check':
            self.require_phone_number(html=login_response.text,
                                      session=session)

        session_cookies = ('remixsid' in session.cookies,
                           'remixsid6' in session.cookies)
        if any(session_cookies):
            logger.info('Session is already established')
            return None
        else:
            message = 'Authorization error: incorrect password or ' \
                      'authentication code'
            logger.error(message)
            raise VkAuthError(message)
Example #12
0
    def do_login(self, session):
        """Do vk login

        :param session: vk_requests.utils.LoggingSession: http session
        """

        response = session.get(self.LOGIN_URL)
        login_form_action = parse_form_action_url(response.text)
        if not login_form_action:
            raise VkAuthError('VK changed login flow')

        login_form_data = {'email': self._login, 'pass': self._password}
        response = session.post(login_form_action, login_form_data)
        logger.debug('Cookies: %s', session.cookies)

        response_url_query = parse_url_query_params(
            response.url, fragment=False)
        act = response_url_query.get('act')
        logger.debug('response_url_query: %s', response_url_query)

        # Check response url query params firstly
        if 'sid' in response_url_query:
            self.require_auth_captcha(
                query_params=response_url_query,
                form_text=response.text,
                login_form_data=login_form_data,
                session=session)

        elif act == 'authcheck':
            self.require_sms_code(html=response.text, session=session)

        elif act == 'security_check':
            self.require_phone_number(html=response.text, session=session)

        session_cookies = ('remixsid' in session.cookies,
                           'remixsid6' in session.cookies)
        if any(session_cookies):
            # Session is already established
            logger.info('Session is already established')
            return None
        else:
            message = 'Authorization error (incorrect password)'
            logger.error(message)
            raise VkAuthError(message)
Example #13
0
    def do_login(self, session):
        """Do vk login

        :param session: vk_requests.utils.LoggingSession: http session
        """

        response = session.get(self.LOGIN_URL)
        login_form_action = parse_form_action_url(response.text)
        if not login_form_action:
            raise VkAuthError('VK changed login flow')

        login_form_data = {'email': self._login, 'pass': self._password}
        response = session.post(login_form_action, login_form_data)
        logger.debug('Cookies: %s', session.cookies)

        response_url_query = parse_url_query_params(response.url,
                                                    fragment=False)
        act = response_url_query.get('act')
        logger.debug('response_url_query: %s', response_url_query)

        # Check response url query params firstly
        if 'sid' in response_url_query:
            self.require_auth_captcha(query_params=response_url_query,
                                      form_text=response.text,
                                      login_form_data=login_form_data,
                                      session=session)

        elif act == 'authcheck':
            self.require_sms_code(html=response.text, session=session)

        elif act == 'security_check':
            self.require_phone_number(html=response.text, session=session)

        session_cookies = ('remixsid' in session.cookies, 'remixsid6'
                           in session.cookies)
        if any(session_cookies):
            # Session is already established
            logger.info('Session is already established')
            return None
        else:
            message = 'Authorization error (incorrect password)'
            logger.error(message)
            raise VkAuthError(message)
Example #14
0
    def do_implicit_flow_authorization(self, session):
        """ Standard OAuth2 authorization method. It's used for getting access token
        More info: https://vk.com/dev/implicit_flow_user
        """
        logger.info('Doing implicit flow authorization, app_id=%s',
                    self.app_id)
        auth_data = {
            'client_id': self.app_id,
            'display': 'mobile',
            'response_type': 'token',
            'scope': self.scope,
            'redirect_uri': 'https://oauth.vk.com/blank.html',
            'v': self.api_version
        }
        response = session.post(url=self.AUTHORIZE_URL,
                                data=stringify_values(auth_data))
        url_query_params = parse_url_query_params(response.url)

        if 'expires_in' in url_query_params:
            logger.info('Token will be expired in %s sec.' %
                        url_query_params['expires_in'])
        if 'access_token' in url_query_params:
            return url_query_params

        # Permissions are needed
        logger.info('Getting permissions')
        action_url = parse_form_action_url(response.text)
        logger.debug('Response form action: %s', action_url)

        if action_url:
            response = session.get(action_url)
            url_query_params = parse_url_query_params(response.url)
            return url_query_params
        try:
            response_json = response.json()
        except ValueError:  # not JSON in response
            error_message = 'OAuth2 grant access error'
            logger.error(response.text)
        else:
            error_message = 'VK error: [{}] {}'.format(
                response_json['error'], response_json['error_description'])
        logger.error('Permissions obtained')
        raise VkAuthError(error_message)
Example #15
0
    def do_oauth2_authorization(self, session):
        """ OAuth2. More info: https://vk.com/dev/auth_mobile
        """
        logger.info('Doing oauth2')
        auth_data = {
            'client_id': self.app_id,
            'display': 'mobile',
            'response_type': 'token',
            'scope': self.scope,
            'v': self.api_version
        }
        response = session.post(url=self.AUTHORIZE_URL,
                                data=stringify_values(auth_data))
        url_query_params = parse_url_query_params(response.url)
        if 'expires_in' in url_query_params:
            logger.info('Token will be expired in %s sec.' %
                        url_query_params['expires_in'])
        if 'access_token' in url_query_params:
            return url_query_params

        # Permissions are needed
        logger.info('Getting permissions')
        action_url = parse_form_action_url(response.text)
        logger.debug('Response form action: %s', action_url)

        if action_url:
            response = session.get(action_url)
            url_query_params = parse_url_query_params(response.url)
            return url_query_params
        try:
            response_json = response.json()
        except ValueError:  # not JSON in response
            error_message = 'OAuth2 grant access error'
            logger.error(response.text)
        else:
            error_message = 'VK error: [{}] {}'.format(
                response_json['error'], response_json['error_description'])
        logger.error('Permissions obtained')
        raise VkAuthError(error_message)
Example #16
0
    def do_oauth2_authorization(self, session):
        """ OAuth2. More info: https://vk.com/dev/auth_mobile
        """
        logger.info('Doing oauth2')
        auth_data = {
            'client_id': self.app_id,
            'display': 'mobile',
            'response_type': 'token',
            'scope': self.scope,
            'v': self.api_version
        }
        response = session.post(url=self.AUTHORIZE_URL,
                                data=stringify_values(auth_data))
        url_query_params = parse_url_query_params(response.url)
        if 'expires_in' in url_query_params:
            logger.info('Token will be expired in %s sec.' %
                        url_query_params['expires_in'])
        if 'access_token' in url_query_params:
            return url_query_params

        # Permissions is needed
        logger.info('Getting permissions')
        form_action = parse_form_action_url(response.text)
        logger.debug('Response form action: %s', form_action)

        if form_action:
            response = session.get(form_action)
            url_query_params = parse_url_query_params(response.url)
            return url_query_params
        try:
            response_json = response.json()
        except ValueError:  # not JSON in response
            error_message = 'OAuth2 grant access error'
            logger.error(response.text)
        else:
            error_message = 'VK error: [{}] {}'.format(
                response_json['error'], response_json['error_description'])
        logger.error('Permissions obtained')
        raise VkAuthError(error_message)
Example #17
0
 def test_parse_form_action(self):
     html = get_fixture('require_phone_num_resp.html')
     action_url = utils.parse_form_action_url(html)
     self.assertEqual(
         action_url,
         '/login.php?act=security_check&to=&hash=4b07a4650e9f22038b')
Example #18
0
 def test_parse_form_action(self):
     html = get_fixture('require_phone_num_resp.html')
     form = utils.parse_form_action_url(html)
     self.assertEqual(
         form, '/login.php?act=security_check&to=&hash=4b07a4650e9f22038b')