СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Авторизация в VK API, используя логин и пароль в черновиках

Давно хотелось написать какое-нибудь приложение, используя VK API. Решено было написать некий каркас, добавляя плагины к которому можно было бы реализовать какие-то мелкие задачи, которые нужны в данный момент: от скачивания музыки до банального поддержания аккаунта онлайн. Запускать данное творение планировалось как на сервере, так и на ПК. С проблемами, вставшими на моем пути во время разработки, включая озвученную в заголовке, я и хотел бы вас познакомить.

Шаг 0. Изучение документации


Итак, задача поставлена, теперь необходимо изучить платформу VK API. Ознакомившись с методами было замечено, что многие из них требуют получения access_token, или, проще говоря, авторизации пользователя.

Способов авторизации было предложено три:
  1. OAuth-авторизация
  2. Прямая авторизация
  3. Авторизация с использованием официального приложения (предоставляется в SDK)

Теперь подробнее о методах в порядке возрастания их полезности:

Авторизация с использованием официального приложения

Приложение состыковывается с официальным приложением для Android или iOS, которое дает ему интерфейс для взаимодействия с API.
Собственно, без комментариев, способ совсем для других платформ и задач.

OAuth-авторизация

Необходимо открыть страницу авторизации в браузере, где пользователь, если он еще не авторизован на сайте, введет свой логин и пароль и разрешит доступ к его аккаунту.
Этот способ не понравился сразу по двум причинам: во-первых, токен таким образом необходимо получать каждые 24 часа, во-вторых, для его получения нужно каждый раз заходить на сервер, открывать lynx, авторизовываться и разрешать доступ. Не очень удобно. Есть, конечно, такой вариант, но всё-таки решено было поискать что-то другое

Прямая авторизация

Передача логина и пароля непосредственно GET-запросом на определенный URL. Токен в итоге получается бессрочный и без привязки по IP.
Идеально подходящий, казалось бы, способ, если бы не одно «но»:

Внимание! Доступ к этому типу авторизации может быть получен только после предварительного согласования с администрацией ВКонтакте.

Для подачи заявки на получение доступа Вам необходимо обратиться в службу поддержки по адресу vk.com/support, указав ID Вашего приложения.

В настоящий момент эта возможность предоставляется только для платформ, не поддерживающих стандартную авторизацию. В заявке необходимо кратко описать функционал приложения.

Объяснять, что пишу просто каркас для любой своей будущей идеи, думаю, было бессмысленно, поэтому пришлось искать какие-то обходные пути.

Шаг 1. Обходные пути


Расстроившись тем фактом, что простым смертным получить доступ к прямой авторизации достаточно сложно, я уже чуть было не похоронил свою идею.
Однако, в один прекрасный день, во время чтения ленты новостей в официальном приложении VK на планшете под управлением Windows 8, в голову пришла мысль: а почему бы не взять access_token из этого приложения, он ведь бессрочный и без привязки к IP. Ну, или еще круче, перехватить app_id и app_secret во время авторизации официального приложения. Всё бы ничего, если бы не авторизация, конечно же, по https протоколу.
Загоревшись идеей кражи app_id и app_secret пришла в голову еще одна идея — декомпилировать клиент и попробовать поискать там.
Сказано — сделано: наверняка metro-приложение VK написано на C#, значит нужно найти C# декомпилятор. Первым в Google нашёлся JetBrains dotPeek. Хорошо, попробуем.
Далее неплохо было бы найти само приложение VK. После не очень долгого поиска было выяснено, что metro-приложения в Windows 8.1 хранятся в скрытой папке C:\Program Files\WindowsApps.
Отлично! Пытаемся зайти и видим:



Мы, вроде бы, администраторы, тыкаем на «Продолжить»:



Весело, зайдём на вкладку «Безопасность», там нам предложат задать особые разрешения в «Дополнительно», зайдем в «Дополнительно»:



Поменяем владельца на себя, щелкнув на «Изменить», введя в диалоге свой email учетной записи microsoft, либо имя локального пользователя и щелнув на «Проверить имена». Сохраним всё это и теперь мы можем зайти в папку с нашими metro-приложениями. Ищем папку с VK, забираем оттуда VK.exe и скармливаем его нашему декомпилятору. Структура приложения видна для нас идеально, все названия функций и классов сохранились, недолгим гулянием по классам находим функцию Authorize, содержащую строку req, в которой есть два замечательных параметра:



Вуаля! client_id и client_secret наши.
client_id и client_secret для копирования
client_id=3697615
client_secret=AlVXZFMUqyrnABp8ncuU

Теперь мы можем авторизовываться, используя прямую авторизацию!
Попользовавшись данными client_id и client_secret мне все-таки стало интересно, что ответит поддержка на возможность их использования. После небольшой дискуссии был получен следующий ответ:



Интересная, конечно, позиция. Хорошо, расслабляемся и пользуемся.

Шаг 2. Собственно каркас


Желаемый каркас всё-таки был написан. В качестве языка программирования был выбран Python.
Состоит он из ядра и подключаемых плагинов. Ядро осуществляет авторизацию, работу с sqlite базой данных, импорт плагинов, опрос longpoll-сервера.
Плагины гибко взаимодействуют с ядром. О структуре плагина:
Чтобы ядро восприняло файл как плагин, в нем должна быть объявлена переменная:

__vkbuddyplugin__ = True

Для того, чтобы добавить параметры в конфиг-файл, плагину необходимо объявить переменную config_parameters:

config_parameters = [
    {'name': 'parameter_name', # имя параметра
     'required': False, # bool, является ли параметр обязательным
     'description': 'parameter_description', # описание параметра
     'default': 'parameter_value', # значение параметра по умолчанию
     'typ': str}, # тип параметра
    ...
]

Чтобы создать таблицы в БД (если они еще не существуют), необходимо объявить переменную sql_tables:

sql_tables = [
    {'name': 'table_name', # имя таблицы
     'structure':( # структура таблицы: пары (имя столбца, тип столбца)
        ('id', int), 
        ('column_name', float)
     )},
    ...
]

Также реализован набор стандартных хендлеров (добавить новые хендлеры можно и в плагинах, так уже реализован хендлер текстовых команд).

Стандартные хендлеры:
  • before_auth_handlers — функции вызываются перед авторизацией, с единственным параметром — основным объектом, в котором можно получить доступ к VK API, хоть это и бесполезно перед авторизацией
  • after_auth_handlers — функции вызываются после авторизации, с тем же единственным параметром
  • exit_handlers — функции вызываются перед выходом, так же с единственным параметром
  • longpoll_handlers — функции вызываются при получении сообщения от longpoll-сервера, параметров здесь много, что они значат можно посмотреть в документации по VK API: (vkbuddy, code, msgid, flags, from_id, ts, subj, text, attachments)

На github можно ознакомиться с результатом, примерами плагинов и прочим, а также поучаствовать в разработке.

Спасибо за внимание!

комментарии (10)

+2
+3 –1
Xlab ,  
Забавно, сами же в документации к API пишут:
При клиентской авторизации ключ доступа к API access_token выдаётся приложению без необходимости раскрытия секретного ключа приложения. Поэтому никогда не указывайте Ваш секретный ключ внутри кода приложения из-за возможности его декомпиляции и использования злоумышленниками.
0
+1 –1
GavYur ,  
Действительно не очень логично их поведение.
С одной стороны не дают всем желающим прямую авторизацию, а с другой говорят, что ничего плохого в ней для всех нет.
При чем если бы они дали эту прямую авторизацию всем приложениям, какие-то из них они могли бы банить, если бы как-то раскрылся факт утечки логинов и паролей, забанить же все официальные приложения как-то сложновато, по-моему.
А Ваша цитата относится, скорее всего, к OAuth-авторизации, для нее секретный ключ действительно не нужен. Авторизоваться же прямой авторизацией не включая ключ в код приложения не представляется возможным.
–3
+1 –4
Accetone ,  
Спасибо большое, использование OAuth тоже отбило желание что-либо писать для десктопа. Теперь есть шанс, что собственные разработки возобновяться.
+3
+4 –1
ahmpro ,  
Ну почему?! Почему некоторые так боятся OAuth? Если сам не хочешь писать аутентификацию, возьми библиотеку. И все, проблема решена, а профита много.
0
Accetone ,  
Дело не в реализации, конечно же. Субъективно не нравиться окно браузера внутри приложения на каком-либо этапе работы с ним (в данном случае аутентификация).
0
kolyaflash ,   * (был изменён)
Возможно потому, что становится проблематично работать с API в «серверных» приложениях (нельзя получить/обновить access token без аутентификации в браузере).

Иногда такое необходимо даже для ВК.
+4
Shchvova ,  
Я являюсь автором приложения для ВКонтакте под пратформу на которой нельзя сделать OAuth авторизацию — нету браузера. Объяснив это поддержке мне дали ключ для авторизации по паролю.
Вы в свою очередь нарушаете пользовательское соглашение, декомпилируете код. В некоторых странах это является незаконным и грозит уголовной ответственностью. Даже если идти в законность, то Вы явно поступаете некрасиво по отношению к инфраструктуре социальной сети и программистам которые под нее и ее разрабатывают.
Да и отношения к АПИ не имеет никакого. В чем собственно пост? Как тырять ключи с чужого кода? Или как сделать rest запрос?
+3
zelenin ,  
таких статей (о прямой авторизации и декомпиляции чужого приложения с целью получения токена) было уже как минимум 3.
90% статьи — нравственные мучения автора)
+2
kwofy ,  
Этот способ не понравился сразу по двум причинам: во-первых, токен таким образом необходимо получать каждые 24 часа, во-вторых, для его получения нужно каждый раз заходить на сервер, открывать lynx, авторизовываться и разрешать доступ. Не очень удобно. Есть, конечно, такой вариант, но всё-таки решено было поискать что-то другое.

В вк API при получении прав можно указать параметр offline, и при согласии пользователя, вам выдадут бессрочный access_token
0
Dreddik ,  
Ну вы прям усложнили процесс, ведь в сети давно гуляет app_id приложения для Android