После нашего первого анонса на Хабре к нам пришло много новых пользователей из России и одна из самых часто запрашиваемых фич была — поддержка Вконтакте. Почему нет, ведь пользователей сети Вконтакте очень много и наконец с «лайками» из этой соц. сети можно сделать что-то полезное для работы.
У нас уже накопился приличный опыт интеграции с различными API: Twitter, Facebook, Github, Behance и т.д. плюс у нас уже выделился некий boilerplate код, с помощью которого новые интреграции делаются в кратчайшие сроки. Поставив себе цель, порадовать наших пользователей на этой неделе, я вынуждуен признать — это оказалось невыполнимой задачей.
Про причины и то, каким недостатком обладает Вконтакте API, читаем далее.
OAuth, OAuth2 и другие
Первое, на что я смотрю в документации нового сервиса это вид авторизации. OAuth2 стал дефакто стандартом на данный момент и многие поддерживаемые Likeastore сервисы реализуют именно его (отличие составляет лишь Twitter, который реализует OAuth1 и Dribbble, который не реализуюет протокола вовсе, а поддерживает лишь дедовский login/password протокол).
Для тех, кто не знаком суть OAuth2 протокола состоит в том, что вы регистрируете клиенское приложение, которое может быть авторизованно пользователем и через обратные вызовы к серверу, сначала издается т.н. code
, который «обменивается» на токен доступа — access_token
.
Обладая токеном доступа, приложение получает возможность делать запросы от имени пользователя. Это очень удобно, так как все популярные API имееют ряд ограничений (т.н. rate limit) и зная количество разрешенных реквестов на единицу времени, компонент ответсвенный за сбор «лайков» (collector) может правильно расчитывать время следующего реквеста избегая уйти в бан.
Я был рад видеть, что Вконтакте поддерживает именно OAuth2 протокол.
Методы и лайки
Следующее, что нужно было найти это методы которые позволяют получить пользовательские «лайки».
В отличии от всех других API, которые поддерживаются у нас и имееют как правило один метод, типа /favorites
, /likes
и т.п. у Вконтакте их оказалось 5 (любимые пользователи, фотки, посты, видео и линки). Делать 5 реквестов вместо одного, казалось не самой лучше идеей для производительности, более ответы разных методов имели самых разный формат, что немного выпадало из общей архитектуры collector-а.
Позже я заметил, что ВК предлагает т.н. «хранимые процедуры», в которой можно собрать все нужные данные и вернуть их за один HTTP реквест. Вполне рабочее решение, но после опыта с Facebook API batching мне показалось не таким элегантным.
Тем не менее, методы были — все остальное дело техники.
Регистрация приложения и первый реквест
Я зарегистировал первое тестовое Standalone приложение и скоро у меня в руках был access_token
. Все шло как по старой, накатанной схеме. Дело оставалось за кодом, который делает HTTP реквест и разбирает результат (connector).
Но, каково же было мое разочарование, когда в консоли вместо данных я увидел следующий ответ.
{ error:
{ error_code: 5,
error_msg: 'User authorization failed: method is unavailable with server auth.',
request_params: [ [Object], [Object], [Object], [Object], [Object] ] } }
Сначала мне показалось, что что-то не так с кодом обращаения к API но 10 раз пересмотревши код и URL реквеста, я понял — все нормально. Гугл по этому вопросу дал очень мало информации… в документации спецификацию ошибки я не увидел, а результаты поиска вели в древние форумы, ответа в которых небыло.
Меня еще раз насторожило вот это предупрежединие:
Но права доступа были правильные и сознанное мной приложение было Standalone.
Открыв глаза пошире и внимательней прочитавши документацию по Standalone приложениям, я увидел, что они поддерживают только клиентсткую авторизацию!
Разница с серверной, заключается в том, что в качестве response_type
передается значение token
, а шага с «обменом» code на access_token, вообще нет, так как в обратоном вызове сразу присутвует access_token переданный как хеш параметр, т.е. доступный только с клиента и не доступный с сервера. Т.к. обе они называются OAuth2, я не сразу обратил внимание на эту разницу.
Львиная доля API методов ВК, доступны только с клиентской авторизацией. Это открытие ввело меня в реальный ступор, зачем?
И правда, зачем?
Что сподвигло разработчиков Вконтакте на введение подобного ограничения, и почему ВК это единствинный API, который его реализует?
Конечно же, в голову приходят всякие методы обхода данного ограничения (например, вычитывать access_token на клиенте и делать AJAX POST на сервер и после этого его свободно использовать). Я думаю, что при продуктивном брейнсторме может родится еще пару идей, т.е. метод на самом деле ничего не защищает, а лишь добавляет головной боли разработчикам. Но всевозможные «обходы» и «хаки» это не то, как бы мы хотели строить свой продукт.
Не смотря на все мелочи — именно проблема серверного доступа к API поставила крест на поддержке Вконтакте в Likeastore.
ЗЫ. Первичной целью этого поста было обращение к пользователям, а также сообществу с просьбой помочь советом тех кто возможно был в подобной ситуации. Уже в процессе написания, я нашел замечательный пост kimrgrey который описывает туже самую проблему, а также ответ antanubis который объясняет почему это сделано именно так. Его аргументация очень понятна, как по мне, не так убедительна.
Я очень надеюсь, что Вконтакте пересмотрит политику в отношении веб приложений или как минимум откроет серверный доступ к такой информации, как «лайки».
ЗЫЫ. Еще одним вариантом может быть использование Прямой авторизации, но лично я никогда бы не ввел свой пароль от ВК на другом сайте + требуется утвержение администрации, которое можно и не получить или это займет много времени. Но если кто-то пользовался этим способом, был бы рад услышать опыт.
Автор: alexbeletsky