Ошибка API авторизации ВКонтакте: u '{"error": "invalid_request", "error_description": "Ошибка безопасности"}' - PullRequest
0 голосов

Я пытаюсь авторизоваться из моего djano-приложения на vk.com. Я использую запросы и авторизацию клиента. Я пытаюсь авторизоваться таким образом и получаю сообщение об ошибке:

{"error":"invalid_request","error_description":"Security Error"}

Интернет предлагает заново авторизоваться на ВК в браузере, но решения для авторизации из кода не существует.

Мой код:

class VkApiSingleton(object):
    api_version = '5.95'

    def __init__(self,
                 app_id=config.APP_ID,
                 login=config.ACCOUNT_LOGIN,
                 pswd=config.ACCOUNT_PASSWORD,
                 permissions='video,offline,groups'
                 ):
        # type: (int, str, str, str) -> None

        self.app_id = app_id
        self.app_user_login = login
        self.app_user_pass = pswd

        self.access_token = None
        self.user_id = None

        self.session = requests.Session()
        self.form_parser = FormParser()

        self.permissions = permissions

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, 'instance'):
            cls.instance = super(VkApiSingleton, cls).__new__(cls, *args,     **kwargs)
        return cls.instance

    @property
    def get_session(self):
        return self.session

    def _parse_form(self, response):
        # type: (requests.models.Response) -> None
        self.form_parser = FormParser()
        try:
            self.form_parser.feed(str(response.content))
        except Exception as err:
            logger.exception(
                'Error checking HTML form',
                extra={'Error body': str(err)}
            )

    def _submit_form(self, **kwargs):
        # type: (dict) -> requests.models.Response
        if self.form_parser.method == 'post':
            payload = copy.deepcopy(self.form_parser.params)
            if kwargs.get('is_login', False):
                payload.update({
                    'email': self.app_user_login,
                    'pass': self.app_user_pass
                })

        with self.get_session as session:
            try:
                return session.post(self.form_parser.url, data=payload)
            except Exception as err:
                logger.exception(
                    'Error submitting auth form',
                    extra={'Error body': str(err)}
                )
                raise VkApiError('Error submitting auth form: %s' % str(err))

    def _log_in(self):
        # type: () -> requests.models.Response
        response = self._submit_form(is_login=True)
        self._parse_form(response)

        if response.status_code != 200:
            raise VkApiError('Auth error: cant parse HTML form')

        if 'pass' in response.text:
            logger.error(
                'Wrong login or password'
            )
            raise VkApiError('Wrong login or password')

        return response

    def _submit_permissions(self, url=None):
        # type: () -> requests.models.Response
        if 'submit_allow_access' in self.form_parser.params and 'grant_access' in self.form_parser.url:
            return self._submit_form(token_url=url)
        else:
            logger.warning(
                'Cant submit permissions for application'
            )

    def _get_token(self, response):
        # type: (requests.models.Response) -> None

        try:
            params = response.url.split('#')[1].split('&')
            self.access_token = params[0].split('=')[1]
            self.user_id = params[2].split('=')[1]
        except IndexError as err:
            logger.error(
                'Cant get access_token',
                extra={'Error body': str(err)}
            )

    def auth(self):
        auth_url = 'https://oauth.vk.com/authorize?revoke=1'
        redirect_uri = 'https://oauth.vk.com/blank.html'
        display = 'wap'

        request_params = {
            'client_id': self.app_id,
            'scope': self.permissions,
            'redirect_uri': redirect_uri,
            'display': display,
            'response_type': 'token',
            'v': self.api_version
        }

        with self.get_session as session:
            response = session.get(
                auth_url,
                params=request_params
            )    

        self._parse_form(response)

        if not self.form_parser.form_parsed:
            raise VkApiError('Invalid HTML form. Check auth_url or params')
        else:
            login_response = self._log_in()

            permissions_response = self._submit_permissions()

            self._get_token(login_response)

1 Ответ

0 голосов

Если у кого-то есть подобная проблема - я нашел несколько причин этого.

1) Неверный тип авторизации - попробуйте использовать другой тип авторизации (это описано в официальной документации) 2) Слишком много авторизаций.

Я решил проблему следующим образом: 1) Получить токен с «автономным» разрешением «Авторизация клиентского приложения» 2) Каждый раз, когда мне нужно использовать метод vk.api - я проверяю срок действия моего токена с помощью безопасного метода «secure.checkToken» (вам необходимо получить служебный токен, чтобы использовать этот метод. В официальной документации много информации) 3) Если мой токен истекает - я получаю новый.

...