OAuth: описание протокола простым и понятным языком. Полезные ссылки по OAuth. Принцип работы OAuth2

​Заботясь о своих клиентах, команда сервиса Invola реализовала прямое подключение к почте по технологии OAuth 2.0.

В этой статье мы расскажем что это такое, как это работает и как влияет на безопасность данных пользователя.
Мы опустим ряд технических моментов, донося суть технологии простым и понятным для рядовых пользователей языком.

Постоянные пользователи сервиса знают, как порой было неудобно использовать дублирующий email , часто забывая отправлять на него очередное письмо. Мы получали письма с просьбой пересмотреть алгоритм получения счетов и коммерческих в пользу прямого подключения к почте.

По прошествии пары недель плодотворной работы программиста и специалиста по безопасности алгоритм авторизации внедрен и теперь является основным способом подключения клиентов к сервису.

Что такое OAuth?

Если говорить сухим техническим языком, то это протокол авторизации, позволяющий выдать одному сервису (в данном случае Invola) права на доступ к ресурсам пользователя на другом сервисе (доступ к почте).

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

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

В коммуникации между Invola и почтовым сервером используется токен доступа access token (шаг 4-5), который автоматически устаревает через час и обновляется по необходимости (автоматически, без участия пользователя, программным обеспечением Invola).

Теперь поговорим о безопасности, и почему авторизация по OAuth предпочтительнее, чем по логину-паролю .

Когда вы предоставляете любому сервису логин и пароль для доступа к аккаунту (mail.ru, gmail.com), вы фактически предоставляете пароль от всей учетной записи (таким образом можно получить доступ, например, к диску, фотоальбомам и другим личным данным).

Предоставляя доступ через OAuth вы сами выбираете, к каким ресурсам аккаунта вы даете доступ . То есть, пользователь сам контролирует к каким ресурсам он готов дать доступ. Рассмотрим пример запрашиваемых прав при подключении к Invola:

"Просмотр и управление почтой " - для автоматического получения счетов и КП, "просмотр адреса " – для получения e-mail ящика, "просмотр профиля " – для получения имени пользователя (требуется на этапе регистрации).

К сожалению, не все почтовые сервера (включая корпоративные) поддерживают авторизацию по технологии OAuth , в частности популярный сервис Яндекс.Почта. Если у вас почта находится на яндексе, подключиться к нашему сервису в данный момент можно только используя логин-пароль.

Немного о безопасности .

Мы очень хорошо понимаем, насколько критичным для бизнеса является утечка конфиденциальных данных или несанкционированный доступ к данным о клиентах, финансовых операциях, личной переписке. Безопасность данных – один из главных приоритетов нашей работы .

Токены доступа, равно как и пароли для доступа к почте, хранятся на защищенном выделенном сервере баз данных с использованием криптографической схемы на основе динамических ключей.

В итоге стоить отметить, что наши сотрудники не имеют доступ к почтовым серверам и переписке наших пользователей ни при каких условиях.

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

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

|

OAuth 2 – это протокол авторизации, который предоставляет приложениям ограниченный HTTP-доступ к учетным записям пользователей. Он передаёт аутентификацию пользователей сервису, на котором размещены учетные записи, и авторизует сторонние приложения и передаёт им доступ к учетной записи пользователя. OAuth 2 обеспечивает авторизацию веб-приложений и мобильных устройств.

Данное руководство ознакомит вас с ролями OAuth 2, типами авторизации, с потоками и случаями использования OAuth 2.

Роли OAuth

В OAuth существует четыре роли:

  1. Владелец ресурса
  2. Клиент
  3. Сервер ресурсов
  4. Сервер авторизации

Рассмотрим каждую роль подробнее.

Владелец ресурса: пользователь

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

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

Сервер ресурсов и авторизации: API

Сервер ресурсов хранит защищенные учетные записи пользователей, а сервер авторизации проверяет учётные данные пользователя, а затем выдает токены доступа к приложению.

С точки зрения разработчика приложений, API сервиса выполняет роли сервера ресурсов и сервера авторизации. В дальнейшем мы будем ссылаться на эти роли как на сервис или API.

Клиент: приложение

Клиент – это приложение, которое хочет получить доступ к аккаунту пользователя. Прежде чем оно сможет сделать это, пользователь должен авторизоваться в приложении, а API должен подтвердить авторизацию.

Потоки протокола

Роли OAuth взаимодействуют между собой следующим образом:

  • Приложение запрашивает авторизацию пользователя, чтобы получить доступ к сервисным ресурсам.
  • Если пользователь по запросу приложения прошел авторизацию, приложение получает полномочия.
  • Приложение запрашивает токен доступа от сервера авторизации (API).
  • Если приложение проходит проверку подлинности и его полномочия действительны, сервер авторизации (API) выдает ему токен доступа. Авторизация завершена.
  • Приложение запрашивает ресурс с сервера ресурсов (API) и предоставляет токен доступа для проверки подлинности.
  • Если токен доступа действителен, сервер ресурсов (API) обслуживает ресурсы для приложения.

Регистрация приложения

Прежде чем вы сможете использовать OAuth в приложении, вам необходимо зарегистрировать приложение. Это делается через регистрационную форму в разделе Developer или API на веб-сайте сервиса, где нужно предоставить следующую информацию:

  • Название приложения;
  • Сайт приложения;
  • URL обратного вызова или URI переадресации (сюда сервис будет перенаправлять пользователя после того, как он прошел (или не прошел) авторизацию; эта часть приложения будет обрабатывать коды авторизации или токены доступа).

ID и секретный ключ клиента

После регистрации приложения сервис предоставит вам учётные данные приложения, которые можно найти в поле client identifier и client secret. Client ID – это общедоступная строка, которая используется API сервиса для определения приложения; также с её помощью создаются URL-ы авторизации. Client Secret позволяет API сервиса подтвердить подлинность приложения, когда оно запрашивает доступ к аккаунту пользователя. Эти конфиденциальные данные хранятся между приложением и API.

Полномочия авторизации

Полномочия авторизации зависят от метода, используемого приложением для запроса авторизации, а также от типов полномочий, поддерживаемых API. OAuth 2 определяет четыре вида полномочий, каждый из которых полезен в различных случаях:

  1. Код подтверждения: используется в приложениях серверной стороны.
  2. Неявный доступ: используется в веб-и мобильных приложениях (приложениях, которые работают на устройстве пользователя).
  3. Предоставление клиенту пароля: применяется в заведомо безопасных приложениях (например, в принадлежащих сервису приложениях).
  4. Клиентские полномочия: доступ к API приложения.

Код подтверждения

Код подтверждения – самый распространённый тип полномочий, оптимизированный для приложений серверной стороны, в которых исходный код закрыт, а Client Secret недоступен посторонним. Этот поток основан на редиректе, а это означает, что приложение должно иметь возможность взаимодействовать с агентом пользователя (т.е. веб-браузером пользователя) и получать коды авторизации API, которые направляются через агента пользователя.

Поток с кодом подтверждения выглядит так:

  1. Пользователь получает ссылку на код подтверждения.
  2. Пользователь авторизуется. Кликая по ссылке, пользователь подтверждает подлинность данных. Если предоставленные данные неправильные, пользователю будет отказано в авторизации.
  3. Приложение получает код подтверждения. Сервис перенаправляет агента пользователя к URI, который был указан при регистрации клиента, вместе с кодом подтверждения.
  4. Приложение запрашивает токен доступа у API, предоставляя код подтверждения и данные об авторизации, включая client secret.
  5. Приложение получает токен доступа, если авторизация валидна.

Поток неявного доступа

Поток неявного доступа используется мобильными приложениями или веб-приложениями, где конфиденциальность client secret гарантировать нельзя. Этот поток также основан на редиректе, но токен доступа получает агент пользователя, после чего он передаётся приложению. Таким образом он может быть виден пользователю или другим приложениям на устройстве пользователя. Кроме того, этот поток не выполняет проверку подлинности приложения, для этого используется URI (который был зарегистрирован в сервисе).

При неявном доступе токены обновления не поддерживаются.

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

  1. Пользователь получает ссылку неявного доступа, которая запрашивает токен у API.
  2. Пользователь проходит авторизацию, кликнув по ссылке. Если пользователь не может авторизоваться, ему будет отказано в доступе.
  3. Агент пользователя получает токен доступа и Redirect URI.
  4. Агент пользователя следует Redirect URI.
  5. Приложение отправляет сценарий извлечения токена доступа. Приложение возвращает веб-страницу со сценарием, который может извлечь токен доступа из Redirect URI.
  6. Приложение получает токен доступа. Авторизация завершена.

Предоставление клиенту пароля

Данный тип подразумевает, что пользователь передаёт учётные данные непосредственно приложению, которое с их помощью получает токен доступа. Этот тип должен поддерживаться только на сервере авторизации. Кроме того, его следует использовать только в случае, если приложению можно доверять (например, оно принадлежит сервису или операционной системе пользователя).

Получив учётные данные пользователя, приложение запрашивает токен доступа у сервера авторизации. Если учётные данные правильные, сервер авторизации предоставит токен доступа. Авторизация завершена.

Клиентские полномочия

Этот тип предоставляет приложению возможность подключиться к собственному аккаунту сервиса. Такой поток полезен, если приложение хочет обновить свое зарегистрированное описание или redirect URI или получить доступ к другим данным, хранящимся в учетной записи сервиса.

Приложение запрашивает токен доступа, отправляя свои учетные данные, client ID и client secret. . Если учётные данные правильные, сервер авторизации предоставит токен доступа. Авторизация завершена.

Использование токенов доступа

Получая токен доступа, приложение может использовать его, чтобы получить доступ к аккаунту пользователя через API.

Если токен валидный, API обрабатывает запрос. Если токен недействителен, API выдаст ошибку invalid_request.

Поток с обновляемым токеном

После того, как действие токена доступа истечет, API выдаст ошибку invalid_request. Если при вместе с токеном доступа приложение получило токен обновления, сейчас оно может использовать его, чтобы запросить новый токен доступа на сервере авторизации.

Теперь вы знакомы с основами OAuth 2.

Tags: ,
  1. Открытие встроенного браузера со страницей авторизации
  2. У пользователя запрашивается подтверждение выдачи прав
  3. В случае согласия пользователя, браузер редиректится на страницу-заглушку во фрагменте (после #) URL которой добавляется access token
  4. Приложение перехватывает редирект и получает access token из адреса страницы
Этот вариант требует поднятия в приложении окна браузера, но не требует серверной части и дополнительного вызова сервер-сервер для обмена authorization code на access token .
Пример
Открываем браузер со страницей авторизации:
> GET /oauth/authorize?response_type=token&client_id=464119 HTTP/1.1 > Host: connect.mail.ru

После того, как пользователь выдаст права, происходит редирект на стандартную страницу-заглушку, для Mail.Ru это connect.mail.ru/oauth/success.html :
< HTTP/1.1 302 Found < Location: http://connect.mail.ru/oauth/success.html#access_token=FJQbwq9&token_type=bearer& expires_in=86400&refresh_token=yaeFa0gu

Приложение должно перехватить последний редирект, получить из адреса acess_token и использовать его для обращения к защищенным ресурсам.

Авторизация по логину и паролю

Авторизация по логину и паролю представляет простой POST-запрос, в результате которого возвращается access token . Такая схема не представляет из себя ничего нового, но вставлена в стандарт для общности и рекомендуется к применению только, когда другие варианты авторизации не доступны.
Пример
> POST /oauth/token HTTP/1.1 > Host: connect.mail.ru > Content-Type: application/x-www-form-urlencoded > > grant_type=password&client_id=31337&client_secret=deadbeef&username=api@corp.mail.ru& password=qwerty < HTTP/1.1 200 OK < Content-Type: application/json < < { < "access_token":"SlAV32hkKG", < "token_type":"bearer", < "expires_in":86400, < "refresh_token":"8xLOxBtZp8", < }
Описание в спецификации

Восстановление предыдущей авторизации

Обычно, access token имеет ограниченный срок годности. Это может быть полезно, например, если он передается по открытым каналам. Чтобы не заставлять пользователя проходить авторизацию после истечения срока действия access token "а, во всех перечисленных выше вариантах, в дополнение к access token "у может возвращаться еще refresh token . По нему можно получить access token с помощью HTTP-запроса, аналогично авторизации по логину и паролю.
Пример
> POST /oauth/token HTTP/1.1 > Host: connect.mail.ru > Content-Type: application/x-www-form-urlencoded > > grant_type=refresh_token&client_id=31337&client_secret=deadbeef&refresh_token=8xLOxBtZp8 < HTTP/1.1 200 OK < Content-Type: application/json < < { < "access_token":"Uu8oor1i", < "token_type":"bearer", < "expires_in":86400, < "refresh_token":"ohWo1ohr", < }

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

Пример кросс-авторизации

Вернемся в 2005-й год и представим, что мы пишем социальную сеть. В ней имеется форма импорта контактов из адресной книги GMail. Что нужно для доступа к контактам GMail? Конечно, логин и пароль от ящика. Но если мы попросим ввести их на нашем сайте, пользователь заподозрит неладное. Где гарантия, что мы не сохраняем на сервере введенные пароли? Поэтому нам хочется, чтобы пароль вводился только на сайте GMail , и после этого доступ к контактам через API GMail предоставлялся нашей социальной сети (возможно, на время). Договоримся о терминах.
  • Consumer : потребитель; скрипт обработки формы импорта контактов в социальной сети.
  • Service Provider : поставщик данных; GMail, содержащий в себе данные адресной книги, интересные для Consumer-а.
  • User : пользователь, имеющий аккаунт как у Consumer-а, так и у Service Provider-а.
  • Protected Resource : личные данные; контакты из адресной книги на GMail (т.е. ресурсы Service Provider-а).
  • Provider API : API GMail, позволяющий любому скрипту получить контакты из адресной книги GMail.
Задача OAuth - сделать так, чтобы User имел возможность работать на сервисе Consumer (в соцсети) с защищенными данными Service Provider-а (GMail), вводя пароль к этим данным исключительно на Service Provider-e и оставаясь при этом на сайте Consumer-а. Не так уж и сложно, верно?

Чем OAuth отличается от OpenID?

OAuth часто называют «протоколом для роботов», в отличие от OpenID - «протокола для пользователей». Не путайте их!
  1. OpenID - протокол для ускоренной регистрации. OpenID позволяет пользователю без ввода пароля получить аккаунт на каком-либо сервисе, если он уже зарегистрирован где-то еще в интернете. (И потом можно без ввода пароля входить на сервис, будучи авторизованным «где-то».) Например, если у вас есть аккаунт на Яндексе, вы сможете «входить» с его помощью на любой сервис, поддерживающий OpenID-авторизацию.
  2. OAuth - протокол для авторизованного доступа к стороннему API. OAuth позволяет скрипту Consumer-а получить ограниченный API-доступ к данным стороннего Service Provider-а, если User дает добро. Т.е. это средство для доступа к API.

Милицейская аналогия

Представьте, что вы - сотрудник Уголовного розыска, ищущий концы в деле о краже WebMoney за 1973-й год. Договоримся о терминах:
  • OAuth Consumer : Уголовный розыск.
  • User : сотрудник Уголовного розыска.
  • Service Provider : Картотека архива преступлений.
  1. OpenID: сотрудник Уголовного розыска (User) приходит в Картотеку (Service Provider), предъявляет на входе ксиву (Authorization) и на месте перебирает карточки в поисках информации.
  2. OAuth: сотрудник Уголовного розыска (User) прямо с работы (Consumer) звонит в Картотеку (Service Provider). Он докладывает свою фамилию; если его узнают (Authorization), он просит предоставить список всех преступлений за 1973-й год (API call).
Как видите, OpenID и OAuth - разные вещи. OpenID позволяет вам прямо на месте получить доступ к некоторым ресурсам. OAuth обеспечивает получение части информации с удаленного сервиса через API.

План этой статьи

Прежде чем перейти к основной части, давайте посмотрим, как именно мы будем двигаться.
  1. Рассмотрим проблемы, которые возникают при «ручной» реализации кросс-авторизации.
  2. Поговорим о том, что такое «приложение» и кто такой Consumer.
  3. Коснемся основ криптографии.
  4. Обозначим демо-приложение, которое мы будем писать в этой статье.
  5. Определимся с тестовым сервером OAuth, на котором будем экспериментировать.
  6. Пройдем по всем шагам протокола OAuth и приведем исходники скрипта.

Об изобретении велосипедов

Хороший способ понять что-то - сделать это самому, наступив попутно на все разложенные грабли. Сейчас мы будем изобретать велосипед: попробуем представить, как бы мы решали задачу взаимодействия Consumer-а и Service Provider-а без всяких стандартизированных протоколов.

Во-первых, напишем саму форму импорта контактов с GMail:Далее попросим разработчиков GMail сделать так, чтобы при переходе пользователя по URI /auth.php ему бы выдавалась форма авторизации (в нашем веломире GMail написан на PHP). После успешного ввода пароля пользователь должен редиректиться на сайт, чей URL указан в параметре retpath. Также дополнительно в URL должен передаваться некоторый секретный ключ, который уже можно использовать для доступа к API GMail.

Итак, после ввода пароля пользователь будет возвращаться к нам на сайт по следующему адресу:А мы из скрипта /import.php обратимся к API GMail, передадим в него ключ Y49xdN0Zo2B5v0RR и загрузим контакты:Ну что же, давайте теперь считать грабли (потому что шишки считать будет уже поздно).

Грабли первые: подмена адреса возврата retpath

Ну конечно же, вы догадались, что злоумышленник на своем сайте первым делом разместит ссылкуи заставит вас на нее кликнуть. В результате он получит секретный ключ, который вернул GMail, а значит, и ваши контакты:

Грабли вторые: «подслушивание» секретного ключа

Предположим, мы как-то защитили retpath, и он теперь может указывать только на наш сайт. Но проблема с параметром secret остается.Secret можно подсмотреть из-за спины или перехватить методом прослушивания WiFi-трафика. Или на вашем сайте когда-нибудь найдется XSS-уязвимость, позволяющая «утянуть» секретный ключ. Имея значение secret, злоумышленник сможет прочитать вашу адресную книгу. Значит, нужно обезопасить secret от перехвата (в идеале - вообще его не передавать через URL).

Грабли третьи: слишком много редиректов

Если для каждого вызова API требуется разный secret, то нам придется организовывать столько редиректов на сайт Service Provider-а, сколько у нас вызовов. При интенсивном использовании API это работает очень медленно, да и неудобно порядком…

Грабли четвертые: плохая идентификация Consumer-а

GMail, конечно, хочет знать, кто пользуется его API. Разрешить доступ одним сайтам и запретить - другим… Значит, при формировании запроса в форме импорта контактов Consumer (сайт) должен «представляться» Service Provider-у (GMail-у). В нашем случае эту функцию частично выполняет retpath (имя сайта в нем), но данный способ не универсален, т.к. механизм «представления» должен быть задейстсован еще и при вызове API-методов.

Фундамент OAuth

Примечательно, что «подводных граблей» осталось еще много. Я не буду их здесь описывать, потому что эти грабли лежат в Марианской впадине (глубоко, 10920 м). На описание уязвимостей пришлось бы потратить с десяток страниц. Так что я сразу перейду к описанию OAuth, где все проблемы уже решены.

Приложение = Consumer + доступ к API

При работе с OAuth важно, что термин Consumer не ограничивается смыслом «сайт». Consumer - это некоторое приложение , а уж где оно размещено, не так важно. Примеры Consumer-ов из реальной жизни: Но из одного OAuth каши не сваришь. Действительно, все, что дает OAuth, - это возможность авторизоваться на удаленном сервисе (Service Provider) и делать автризованные запросы к API. Не важно, как устроен этот API: это может быть чистый SOAP, REST-подход т. д. Главное, чтобы каждый метод API принимал на вход специальные параметры, передаваемые согласно протоколу OAuth.

Token = Key + Secret

Один из принципов OAuth гласит, что никакие секретные ключи не должны передаваться в запросах открытыми (выше в примере мы рассматривали, почему). Поэтому протокол оперирует понятием Token. Токен очень похож на пару логин + пароль: логин - открытая информация, а пароль - известен только передающей и принимающей стороне. В терминах OAuth аналог логина называется Key, а аналог пароля - Secret. Ситуация, когда Secret известен только отправителю и получателю, но более никому, называется Shared Secret.

Итак, если Consumer и Provider каким-то образом договорятся между собой о Shared Secret, они могут открыто обмениваться в URL соответствующими ключами (Key), не опасаясь, что перехват этих ключей будет опасен. Но как защитить URL с Key от подделки?

Сообщение = Документ + Цифровая подпись

«Цифровая подпись» - звучит страшно, но на самом деле это достаточно очевидная вещь. Когда вы ручкой подписываетесь на каком-либо документе, вы удостоверяете, что этот документ написан вами, а не кем-то другим. Ваша подпись как бы «добавляется» к документу и идет с ним в «одном комплекте».

Аналогично, цифровая подпись добавляется к некоторому блоку данных, удостоверяя: тот, кто сформировал эти данные, не выдает себя за другого. Цифровая подпись не шифрует документ, она лишь гарантирует его подлинность! Поставить подпись позволяет тот самый Shared Secret, который известен получателю и отправителю, но более никому.

Как это работает? Пусть наш $sharedSecret = 529AeGWg, и мы сообщили его шепотом на ухо принимающей стороне. Мы хотим передать сообщение «Мой телефон 1234567» с гарантированной защитой от фальсификации злоумышленником.

  1. Consumer добавляет цифровую подпись к сообщению, в общем виде - $transfer = $message . "-" . md5($message . $sharedSecret); // $transfer = "Мой телефон 1234567" . "-" . md5("Мой телефон 1234567" . "529AeGWg")
  2. Service Provider принимает данные, разбивает их обратно на 2 части - $message и $signature - и проделывает точно такую же операцию: $signatureToMatch = md5($message . $sharedSecret); // $signatureToMatch = md5("Мой телефон 1234567" . "529AeGWg"); Дальше остается только сравнить получившееся значение $signatureToMatch с тем, что было в полученных данных $signature и рапортовать о подделке, если значения не совпали.

Демонстрация работы OAuth на примере простого приложения

Чтобы «вживую пощупать» OAuth, нам потребуются две вещи:
  1. Скрипт, реализующий клиентскую часть протокола. Я написал как раз такой небольшой PHP-скрипт (ссылка на zip-архив). Это виджет, который можно вставлять на PHP-сайты.
  2. Тестовый сервер OAuth, на котором мы сможем экспериментировать. Для этой цели удобно использовать РуТвит: там есть страница http://rutvit.ru/apps/new , которая позволяет добавить тестовое приложение за 30 секунд. (Кстати, URL возврата в форме можно не указывать - мы все равно передаем его из тестового скрипта.)
Глядя на код демо-скрипта и читая пояснения ниже в статье, можно разобраться с деталями протокола.

Вы можете вставить данный виджет на любой PHP-сайт, просто скопировав его код и подправив верстку. Выводятся все твиты с сервиса РуТвит , помеченные указанным хэш-тэгом, а также имеется возможность добавлять новые твиты (тут-то как раз и задействуется OAuth). Виджет использует API и OAuth-авторизацию РуТвита, которые, кстати говоря, совпадают со стандартом API Twitter-а.Вы можете запустить этот скрипт на своем тестовом сервере. Для этого нужно выполнить три действия:

  1. Скачайте код скрипта и разверните его в любую удобную директорию на веб-сервере.
  2. Зарегистрируйте новое тестовое приложение на OAuth-сервере.
  3. После регистрации приложения замените параметры OA_CONSUMER_KEY и OA_CONSUMER_SECRET в скрипте на значения, полученные от сервера.

Регистрация приложения и его параметры

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


После регистрации приложения вам выдается 5 параметров, которые требуются для работы с OAuth. Вот как они могут выглядеть:


Здесь Consumer key и Consumer secret - это своеобразные «логин + пароль» вашего приложения (помните выше разговор о токенах? это как раз один из них). Напомню, что Consumer secret - это Shared Secret, известный только отправителю и получателю, но никому больше. Остальные 3 значения задают служебные URL, смысл которых мы сейчас рассмотрим.

OAuth = Fetch Request Token + Redirect to Authorization + Fetch Access Token + Call API

В примере с GMail мы использовали 2 вида удаленных вызовов: а) редирект через браузер; б) обращение к API изнутри скрипта.

И мы вскрыли ряд проблем с безопасностью, что наводит на мысль: вызовов должно быть больше. Так и происходит в OAuth: добавляются еще промежуточные запросы от скрипта Consumer-а к Provider-у, оперирующие токенами. Давайте их рассмотрим.

  1. Обработка отправки формы. Это не часть OAuth, а часть нашего приложения. Прежде чем обращаться к API Provider-а, мы должны получить от пользователя заказ-наряд на это действие. Вот пример такого «заказа»:
  2. Fetch Request Token (внутренний запрос).
    • Скрипт Consumer-а обращается к Request token URL Provider-а: например, api.rutvit.ru/oauth/request_token . В запросе передается Consumer key - «логин приложения», а сам запрос подписывается при помощи Consumer secret - «пароля приложения», что защищает его от подделки.
    • В ответ Provider генерирует и возвращает «заполненный мусором» токен, который называется Request Token. Он нам еще пригодится, поэтому мы должны сохранить его где-нибудь - например, в сессионной переменной $S_REQUEST_TOK.
  3. Redirect to Authorization (через редирект в браузере). Теперь у нашего приложения есть уникальный Request Token. Требуется получить у пользователя разрешение на использование этого токена, т.е. попросить его авторизовать Request Token .
    • Consumer редиректит браузера на специальный Authorize URL Provider-а: например, api.rutvit.ru/oauth/authorize . В параметрах передается Request Token Key.
    • Provider выводит форму авторизации для своего пользователя и, если он авторизовался, редиректит браузер назад. Куда именно? А мы указываем это в параметре oauth_callback.
  4. Fetch Access Token (внутренний запрос). Итак, браузер вернулся в наше приложение после серии редиректов. Это значит, что авторизация на Provider-е прошла успешно, и Request Token разрешен к работе. Однако в OAuth для безопасности каждый токен имеет свое собственное, строго ограниченное назначение. Например, Request Token используется только для получения подтверждения от пользователя, и больше ни для чего. Для доступа к ресурсам нам нужно получить новый токен - Access Token - или, как говорят, «обменять Request Token на Access Token».
    • Consumer обращается к Access token URL - например, api.rutvit.ru/oauth/access_token , - и просит выдать ему Access Token взамен имеющегося у него Request Token-а. Запрос подписывается цифровой подписью на основе Request Token secret.
    • Provider генерирует и возвращает Access Token, заполненный «мусором». Он также помечает в своих таблицах, что для этого Access Token-а разрешен доступ к API. Наше приложение должно сохранить у себя Access Token, если оно собирается использовать API в дальнейшем.
  5. Call API (внутренний запрос). Ну что же, теперь у нас есть Access Token, и мы можем передавать его key при вызове методов API.
    • Consumer генерирует запрос к API Provider-а (например, используя POST-запрос согласно REST-идеологии). В запросе передается Access Token Key, а подписывается он при помощи Shared Secret этого токена.
    • Provider обрабатывает API-вызов и возвращает данные приложению.

Конец скрипта: вывод виджета

Окончание скрипта должно быть понятно и без подробных разъяснений.
Листинг 14: Окончание скрипта: вывод виджета
// конец case } } // Получаем все имеющиеся твиты. $text = file_get_contents("http://api.rutvit.ru/search.xml?rpp=5&q=" . urlencode("#" . TAG)); $TWEETS = new SimpleXMLElement($text); // Shortcut для вывода сообщения с перекодировкой и квотингом. function e($text, $quote = 1) { $text = iconv("utf-8", ENCODING, $text); echo $quote? htmlspecialchars($text) : $text; } ?>
status as $tweet) {?>
user->screen_name)?>: text_formatted, 0)?>
?action=form_is_sent" style="margin: 1em 0 0 0">

Полезные ссылки по OAuth

  • rutvit
Добавить метки
  1. Открытие встроенного браузера со страницей авторизации
  2. У пользователя запрашивается подтверждение выдачи прав
  3. В случае согласия пользователя, браузер редиректится на страницу-заглушку во фрагменте (после #) URL которой добавляется access token
  4. Приложение перехватывает редирект и получает access token из адреса страницы
Этот вариант требует поднятия в приложении окна браузера, но не требует серверной части и дополнительного вызова сервер-сервер для обмена authorization code на access token .
Пример
Открываем браузер со страницей авторизации:
> GET /oauth/authorize?response_type=token&client_id=464119 HTTP/1.1 > Host: connect.mail.ru

После того, как пользователь выдаст права, происходит редирект на стандартную страницу-заглушку, для Mail.Ru это connect.mail.ru/oauth/success.html :
< HTTP/1.1 302 Found < Location: http://connect.mail.ru/oauth/success.html#access_token=FJQbwq9&token_type=bearer& expires_in=86400&refresh_token=yaeFa0gu

Приложение должно перехватить последний редирект, получить из адреса acess_token и использовать его для обращения к защищенным ресурсам.

Авторизация по логину и паролю

Авторизация по логину и паролю представляет простой POST-запрос, в результате которого возвращается access token . Такая схема не представляет из себя ничего нового, но вставлена в стандарт для общности и рекомендуется к применению только, когда другие варианты авторизации не доступны.
Пример
> POST /oauth/token HTTP/1.1 > Host: connect.mail.ru > Content-Type: application/x-www-form-urlencoded > > grant_type=password&client_id=31337&client_secret=deadbeef&username=api@corp.mail.ru& password=qwerty < HTTP/1.1 200 OK < Content-Type: application/json < < { < "access_token":"SlAV32hkKG", < "token_type":"bearer", < "expires_in":86400, < "refresh_token":"8xLOxBtZp8", < }
Описание в спецификации

Восстановление предыдущей авторизации

Обычно, access token имеет ограниченный срок годности. Это может быть полезно, например, если он передается по открытым каналам. Чтобы не заставлять пользователя проходить авторизацию после истечения срока действия access token "а, во всех перечисленных выше вариантах, в дополнение к access token "у может возвращаться еще refresh token . По нему можно получить access token с помощью HTTP-запроса, аналогично авторизации по логину и паролю.
Пример
> POST /oauth/token HTTP/1.1 > Host: connect.mail.ru > Content-Type: application/x-www-form-urlencoded > > grant_type=refresh_token&client_id=31337&client_secret=deadbeef&refresh_token=8xLOxBtZp8 < HTTP/1.1 200 OK < Content-Type: application/json < < { < "access_token":"Uu8oor1i", < "token_type":"bearer", < "expires_in":86400, < "refresh_token":"ohWo1ohr", < }
  • Сергей Савенков

    какой то “куцый” обзор… как будто спешили куда то