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
Comments 40
Comments Comments 40

Popular right now

Top of the last 24 hours

Information

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

Habr blog