Pull to refresh

Поддержка протокола XMPP в Mail.Ru Агенте и «секреты» авторизации на XMPP-сервере Facebook

Mail.ru Group corporate blog
Мы рады сообщить вам о выходе Mail.Ru Агента версии 5.8 для Windows!

Главная «фича» этой версии – поддержка протокола XMPP (Jabber), которая ранее уже появилась в мобильных клиентах для платформ Symbian и Java 2 Micro Edition. Поскольку мобильным мессаджингом пользуется наиболее активная и технически «продвинутая» часть нашей аудитории, эксперимент с XMPP мы начали именно с мобильных платформ. Однако «фича» неожиданно оказалась довольно популярной и востребованной, в том числе, и на десктопе.

Основная идея поддержки этого протокола заключается в том, чтобы сделать возможным обмен IM-сообщениями с пользователями социальных сетей «Вконтакте» и Facebook, которые не так давно открыли публичный интерфейс к своим внутренним системам мессаджинга по протоколу XMPP. Как показал наш опыт с Мобильным Агентом, это наиболее частый случай использования XMPP-клиента.

Однако, несмотря на «заточенность» под социальные сети, наша реализация протокола поддерживает большинство популярных расширений (XEP'ов – XMPP Extenstion Protocol), так что Mail.Ru Агент можно использовать в качестве клиента для подключения к самым произвольным XMPP-серверам. «Из коробки» поддерживаются сервисы «Вконтакте», Facebook, Google Talk, Яндекс.Онлайн и QIP, однако при необходимости можно подключить любую учетную запись (например, на Jabber.Ru) – достаточно лишь указать в настройках JID (Jabber ID) и пароль (IP-адрес сервера будет определен автоматически по SRV-запросу к DNS).

Если говорить об особенностях реализации XMPP-клиента, то с основными проблемами мы столкнулись в области авторизации пользователей.Дело в том, что XMPP-серверы Вконтакте и Facebook авторизуют пользователей не по логинам, которые используются для авторизации на веб-сервисах и представляют собой различные адреса электронной почты, а по JID вида idXXXX@vk.com и ALIAS@chat.facebok.com, соответственно. Это логично, поскольку в протоколе XMPP домен в JID пользователя должен совпадать с доменом XMPP-сервера, к которому относится этот JID.

В случае с Вконтактом idXXXX – это некоторый внутренний идентификатор пользователя, который можно посмотреть, например, в URL своего профиля. C Facebook все оказалось несколько сложнее. По умолчанию у пользователя нет вообще никакого ALIAS'а — и хотя его можно задать в настройках своей учетной записи, в ряде случаев для подтверждения этого действия необходимо пройти SMS-авторизацию (ввести код, отправленный Facebook'ом в виде SMS-сообщения). А SMS в Россию Facebook… не доставляет (во всяком случае, так было пару месяцев назад).

Так или иначе, идея заставлять пользователя вводить в настройках Mail.Ru Агента некие «магические» идентификаторы (с которыми он никогда не сталкивается в повседневной жизни) показалась нам неудачной, так что мы сразу решили поддержать авторизацию в XMPP по тем же логину и паролю, которые используются для авторизации на вебе.

Со Вконтактом все оказалось просто – мы связались с нашими коллегами, и они предоставили нам простой API, возвращающий idXXXX по «вебовому» логину/паролю. Дальнейшее было делом техники: достаточно просто взять idXXXX и пароль, указанный пользователем в настройках Mail.Ru Агента, и авторизоваться на XMPP-сервере стандартным методом DIGEST-MD5.

Facebook же заставил нас повозиться. Кроме неудобной для пользователя авторизации по JID (методами PLAIN и DIGEST-MD5), их XMPP-сервер поддерживает также SASL-авторизацию. В теории, идея тривиальна. В клиентском приложении запускается браузер, и в нем пользователь авторизуется по своему обычному логину/паролю. После успешной авторизации сервер возвращает клиенту браузеру токен, с которым (после выполнения некоторых преобразований) выполняется уже авторизация по протоколу XMPP. К сожалению, несмотря на простоту этого механизма, в нем есть несколько тонкостей, которые документированы у Facebook весьма туманно, так что нам пришлось изучить немало девелоперских форумов и много экспериментировать. :)

Результатами этого небольшого исследования мы рады поделиться с вами (на случай, если вы когда-нибудь решите написать свой XMPP-клиент для Facebook).

Итак, для начала нам понадобится создать свое приложение в «админке» Facebook.

Помимо очевидных опций, в настройках приложения нужно отключить опцию «Disable Deprecated Auth Methods».

Для того, чтобы авторизоваться через SASL, нам необходимо получить авторизационный токен. Основная хитрость здесь заключается в правильном формировании http-запроса для OAuth-авторизации. Он должен иметь примерно такой вид:

www.facebook.com/dialog/oauth?client_id=123&response_type=token&redirect_uri=http://agent.mail.ru/&display=popup&scope=xmpp_login,offline_access

client_id здесь – это id вашего приложения,
response_type – тип данных (в данном случае – токен), который вернет сервер в случае успешной авторизации;
redirect_uri – URL, на который будет переадресован браузер после успешной авторизации, домен этого URL обязательно должен совпадать с доменом, указанным в настройках вашего приложения;
scope – запрашиваемые права доступа. Опция xmpp_login позволяет использовать полученный авторизационный токен для SASL-авторизации на XMPP-сервере, а offline_access обеспечивает этому токену «вечное» время жизни (чтобы у пользователя не было необходимости вводить логин/пароль при каждом подключении).

В случае успешной авторизации http-сервер переадресует браузер на redirect_uri, добавив к нему в качестве GET-параметра переменную access_token (собственно, авторизационный токен). Значение этой переменной представляет собой строку, разделенную на три части символом «|»:

216315195049043|19d8c4fcd929d1324ce9ed5f.1-100001685116a73|ifwc5qPhOguAhc3vaRmtCBnqv7E

Нас интересует средняя часть – ключ сессии.

Теперь необходимо установить соединение с XMPP-сервером и запросить у него авторизацию по «пропритарному» методу X-FACEBOOK-PLATFORM. В ответ на этот запрос сервер вернет challenge – строку примерно такого вида:

version=1&method=auth.xmpp_login&nonce=859F2F4CD0F6B245A22EB6382D9689DB

Далее мы формируем примерно такую строку:

api_key=321call_id=407808859method=auth.xmpp_loginnonce=859F2F4CD0F6B245A22EB6382D9689DB session_key=19d8c4fcd929d1324ce9ed5f.1-100001685116a73v=1.02b613865ef9e9f742caac8d163da3631

где api_key – это ключ API вашего приложения (не путать с ID приложения);
call_id – случайное число;
method – параметр со значением, скопированным из challenge;
nonce – идентификатор, скопированный из challenge;
session key – ключ сессии, полученный из токена;
v – некий номер версии (Facebook рекомендует использовать 1.0).

Значение после номера версии (2b613865ef9e9f742caac8d163da3631) соответствует секретному ключу вашего приложения (не путать с ключом API и ID приложения).

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

api_key=321&call_id=407808859&method=auth.xmpp_login&nonce=859F2F4CD0F6B245A22EB6382D9689DB&session_key=19d8c4fcd929d1324ce9ed5f.1-100001685116a73&sig=da0f8f0363a9f7e1cb479fcd88f10716&v=1.0

где все параметры аналогичны предыдущей строке, а sig – md5() от нее. Здесь параметры уже разделяем амперсандом.

Полученную строку кодируем методом base64 и авторизуемся с этими данными на XMPP-сервере:

<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">YXBpX2tleT0zMjEmY2FsbF9pZD00MDc4MDg4NTkmbWV0aG9kPWF1dGgueG1wcF9sb2dpbiZub25jZT04NTlGMkY0Q0QwRjZCMjQ1QTIyRUI2MzgyRDk2ODlEQiAmc2Vzc2lvbl9rZXk9MTlkOGM0ZmNkOTI5ZDEzMjRjZTllZDVmLjEtMTAwMDAxNjg1MTE2YTczICZzaWc9IGRhMGY4ZjAzNjNhOWY3ZTFjYjQ3OWZjZDg4ZjEwNzE2JnY9MS4w</response>

Вуаля, мы авторизовались на XMPP-сервере и можем обмениваться с ним соощениями.

Недостатком OAuth/SASL-авторизации является фактическая невозможность ее реализации на мобильных клиентах для таких платформ как J2ME и Symbian, поскольку API этих ОС не предоставляют пользовательскому приложению непосредственного доступа к браузеру (через который осуществляется получение авторизационного токена).

Приглашаем всех желающих попробовать Mail.Ru Агент 5.8 и особенно ждем впечатлений насчет работы нашего XMPP-клиента.

Илья Наумов,
руководитель проекта Mail.Ru Агент
Tags:Mail.Ru АгентXMPPВконтактеFacebookФейсбукOAuth
Hubs: Mail.ru Group corporate blog
Total votes 62: ↑46 and ↓16 +30
Views18.1K

Comments 40

Only those users with full accounts are able to leave comments. Log in, please.

Popular right now

Information

Founded
Location
Россия
Website
team.mail.ru
Employees
5,001–10,000 employees
Registered
Representative
Павел Круглов

Habr blog