Bearburger's Nest

Блог Рагимова Романа

Исследование процесса авторизации на сайте VK.com

Возможно, информация из данной заметки устарела!

Доброго времени суток, уважаемые.

Начиная с прошлой недели многие пользователи сторонних разработок на тему «а давайте использовать контент в Вконтакте без захода на сам сайт» могли лицезреть нечто подобное изображению из заголовка. Эта проблема меня никак не волновала, если бы не один «домашний» проектик, которому в админке нужна возможность свободного доступа к VK.

Авторизация ВКонтакте

Для начала, давайте поговорим о текущей схеме кроссдоменной авторизации на «Вконтактике». Так как VK, на данный момент, включает в себя 2 основных сайта (vk.com и vkontakte.ru), администрацией ресурса было принято решение организовать сквозную авторизацию на обоих ресурсах. Это значит, что авторизировавшись на вконтактике, вы свободно можете набрать vk.com и попасть на «англоязычный» вариант своего профиля. Особого смысла я в этом не вижу, т.к. большая часть хомячков слыхом не слыхивала о vk.com, но так уж оно есть и приходится с этим жить.

Как же «выглядит» процесс авторизации на сервисе через браузер?

  1. Пользователь запрашивает страницу vkontakte.ru и получает во ответ почти обычную HTML страницу. Почему «почти», потому что в нее встроен то ли некий JS, то ли iframe (признаться честно не разбирался), который запрашивает у vk.com информацию об этом пользователе. Судя по всему, если пользователь авторизирован на vk.com и по какой-то причине не прошел процедуру сквозной авторизации, эта авторизация будет проведена при первом входе на русскоязычную версию.
  2. Далее пользователь вводит свои логин с паролем. Дорогой читатель, если ты думаешь, что данные сразу отправляют скрипту, ты глубоко заблуждаешься. Сначала отправляется AJAX запрос на http://vkontakte.ru/login.php с одним единственным параметром op значение которого a_login_attempt. Ответом всегда служит строка vklogin. Сакральный смысл сего действа до сих пор скрыт от меня. Возможно, где-то в зарослях JS кода скрыт набор вариантов серверов для логина и vklogin это один из них. Возможно, это своеобразная защита от тупого копирования страницы с целью фишинга (хотя, не понимаю как это может защитить, кроме того, что кнопка будет неактивна и «хацкер» пойдет искать знающего знакомого). В любом случае это действо происходит всегда и лишь после него браузер начинает процесс собственно авторизации.
  3. http://login.vk.com/?act=login — пожалуй, самый знаменитый адрес для всех разработчиков, кто занимался выуживанием информации из недр контакта. Именно по этому адресу отправляются ваши логин с паролем. Именно от этого адреса зависит какая страница будет показана следующей.
    • Если введенные данные успешно проходят проверку, пользователю возвращается страница со скрытой формой, которая в автоматическом режиме будет отправлена на http://vkontakte.ru/login.php?op=slogin.
    • Если же логин или пароль неправильны, будет возвращена пустая страница с кодом ответа 302 и заголовком Location: http://vkontakte.ru/

Давайте сравним заголовки запросов к серверу при отправке данных из Flash и браузера

Это запросы из браузера и флеша, соответственно. Я отметил спорные моменты по которым сервер Вконтакта может догадаться, что авторизация проводится не через браузер. Лично я в качестве причины предположил заголовок x-flash-version, как если бы контакт начал закрывать себя от «пиратов». Почему не Referer спросите вы, ну, просто потому что в моей реализации я сам контролирую все заголовки и Referer был заменен на нужный еще в первой версии программы. Ну, на всякий пожарный. Как выяснилось позже, проблема была не в этом.

Итак, главный подозреваемый – заголовок x-flash-version. Гуглу не удалось ответить на главный вопрос — как убрать этот заголовок. Да, вы можете заменить его значение на пустое, но полностью избавиться от него не представляется возможным. Что самое интересное, месяцев пять-шесть назад, когда я разрабатывал первую версию кода для авторизации во ВКонтакте из AIR приложения, этого заголовка не было. Удивительно.

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

Браузер логинился отлично…

Из трех вариантов у нас остался только один — cookies. Итак, в нашем запросе из Flash мы видим куки с именами l и p. Судя по всему, l это идентификатор логинящегося пользователя, а p — хэш пароля. При логине через браузер они устанавливаются в ответе от сервера.

В данном процессе меня заинтересовал другой момент — при повторном логине браузер НЕ отправляет эти куки на сервер. А Flash отправляет. И получает за это «по шапке». А знаете почему это все происходит? Потому что, перед тем как «заходить» надо сначала «выйти» :–)

Думаю, скриншот выхода из Vkontakte через браузер объяснит вам многое.

А когда ВЫ в последний раз «выходили» из Вконтакта в своем приложении?

Думаю, данная проблема актуальна и для PHP, если вы не храните cookies в файлах со случайными именами.

За сим прощаюсь. Надеюсь был полезен.