OAuth 2 это фреймворк для авторизации, который позволяет приложениям получать ограниченный доступ к аккаунтам пользователей через HTTP , таким как Fackebook , GitHub и DigitalOcean . Он работает путем делегирования идентификации пользователя сервису, на котором размещена учетная запись пользователя и авторизационным сторонним приложения имеющим доступ к учетной записи пользователя. OAuth 2 предоставляет авторизационные потоки для десктопных, веб приложений и мобильных устройств.
Это информационное руководство направлено на разработчиков приложений и предоставляет обзор ролей OAuth 2 , типов авторизованных разрешений, используемых ситуаций и потоков.
Давайте начнём с ролей OAuth 2 !
Oauth определяет 4 роли:
Мы разберём каждую роль в следующих подразделах.
Владелец ресурса это пользователь, который использует приложение для доступа к аккаунту. Доступ приложения к аккаунту пользователя ограничен областью авторизационных разрешений (например чтением или записью).
Сервер ресурса хранит защищённые пользовательские аккаунты, а сервер авторизации проверяет личность пользователя и затем выдает приложению маркеры доступа.
С точки зрения разработчиков приложений, АПИ сервиса выполняет обе роли, как сервера ресурса так и сервера авторизации. Мы будем перенаправлять к обоим из этих комбинированных ролей, как роль Сервиса так и роль АПИ.
Клиент это приложение, которое хочет получить доступ к аккаунту пользователя. Перед тем, как оно это сделает, оно должно быть разрешено пользователем и авторизация должна быть проверена АПИ.
Теперь у вас есть представление о том, что из себя представляет роли OAuth, давайте взглянем на диаграмму того, как они в основном взаимодействуют друг с другом:
Вот более подробное объяснение шагов на диаграмме:
Фактический поток этого процесса будет отличаться в зависимости от типа предоставления авторизации находящегося в использовании — это общая идея. Мы будем изучать различные типы предоставления в следующем разделе.
Перед использованием OAuth в Вашем приложении, Вы должны зарегистрировать свое приложение с сервисом. Это делается через регистрационную форму в разделе Разработчика или АПИ веб-сайта сервиса, где Вы будете предоставлять следующую информацию (и вероятно детальную информацию о Вашем приложении):
Перенаправление URI используется там, где сервис будет перенаправлять пользователя после того, как Ваше приложение будет авторизовано или запрещено, следовательно, часть вашего приложения, которая будет обрабатывать коды авторизации или маркеры доступа.
Идентификатор клиента и секретный код клиента
Как только ваше приложение зарегистрировано, сервис будет выдавать «учетные данные клиента» в виде идентификатора клиента и секретного кода клиента. Идентификатор клиента это публичная строка, которая используется АПИ сервиса для идентификации приложения, а так же используется для построения авторизационных URL’ов, которые представляются пользователям. Секретный код клиента используется для установки подлинности приложения для АПИ сервиса, когда приложение запрашивает доступ к аккаунту пользователя и должен быть сохранен в секрете между приложением и АПИ.
В абстрактном потоке протокола выше, первые четыре шага описывают получение предоставления авторизации и маркера доступа. Тип предоставления авторизации зависит от метода используемого приложением для запроса авторизации и типами предоставления поддерживающимися АПИ. OAuth 2 определяет 4 типа предоставления, каждый из которых по своему полезен в разных ситуациях:
Теперь мы будем описывать типы предоставлений более детально, их варианты использования и потоки, в следующих разделах.
Тип предоставления кода авторизации является наиболее используемым так как он оптимизирован под приложения на стороне сервера, где исходный код не показан открыто и конфиденциальность секретного кода клиента может быть сохранена. Это поток на основе перенаправления, что означает что приложение должно быть способно взаимодействовать с юзерагентом (т.е. с браузером пользователя) и получать коды авторизации АПИ, которые направляются через юзерагент.
Когда пользователь кликает (нажимает на) по ссылке, они должны сначала залогиниться (войти) в сервисе, для удостоверения их личности (если конечно они уже не залогинились). Затем сервис запросит у них подтверждение на разрешение или запрет доступа приложения к их аккаунту. Вот пример запроса на доступ к аккаунту приложением:
Авторизация приложения
Обзор разрешений (прав доступа)
- Чтение
Авторизовать приложение Запретить
Если пользователь нажимает на «Авторизовать приложение», то сервис перенаправляет браузер на URI переадресации приложения, который был указан при регистрации клиента, вместе с кодом авторизации. Переадресация будет выглядеть так (предполагая, что адрес приложения «dropletbook.com»):
Шаг 4: Приложение получает маркер доступа
Приложение запрашивает маркер доступа от АПИ передавая код авторизации конечной точке маркера АПИ, вместе с подробной информацией об идентификации, включая секретный код клиента. Вот пример запроса через POST к конечной точке маркера DigitalOcean:
Шаг 5: Приложение получает маркер доступа
{«access_token»:»ACCESS_TOKEN»,»token_type»:»bearer»,»expires_in»:2592000,»refresh_token»:»REFRESH_TOKEN»,»scope»:»read»,»uid»:100101,»info»:{«name»:»Mark E. Mark»,»email»:»[email protected] «}}
Теперь приложение авторизовано! Оно может использовать маркер для доступа к аккаунту пользователя через АПИ сервиса, с ограничениями по доступу, пока маркер не истечёт или не будет отменён. Если маркер обновления был передан, то он может быть использован для запроса новых маркеров доступа, если срок действия исходного маркера истёк.
Тип неявного предоставления используется для мобильных приложений и веб-приложений (т.е. приложений, которые запускаются в браузере), где конфиденциальность секретного кода клиента не гарантируется. Тип неявного предоставления также является потоком на основе переадресации, но маркер доступа даётся браузеру для передачи его приложению, так что он может быть доступен как пользователю, так и другим приложениям на устройстве пользователя. Кроме того, этот поток не проверяет подлинность идентичности приложения и полагается на перенаправление URI (который был зарегистрирован с сервисом), чтобы служить этой цели.
Тип неявного предоставления не поддерживает маркеры обновления.
Поток неявного предоставления в основном работает следующим образом: пользователю предлагается авторизовать приложение, затем сервер авторизации передает маркер доступа обратно браузеру, который в свою очередь передает его приложению. Если Вам интересны подробности, читайте далее.
С типом неявного предоставления, пользователю даётся ссылка авторизации, которая запрашивает маркер от АПИ. Эта ссылка выглядит как ссылка кода авторизации, за тем лишь исключением, что она запрашивает маркер вместо кода (обратите внимание, что тип запроса “маркер”):
Примечание
Когда пользователь нажимает на ссылку, они сначала должны войти в сервис, чтобы подтвердить подлинность их личности (если они ещё не залогинились). Затем им будет предложено сервисом разрешить или запретить доступ приложения к их аккаунту. . Вот пример запроса на доступ к аккаунту приложением:
Авторизация приложения
Thedropletbook хотел бы получить разрешение на доступ к вашей учетной записи
Обзор разрешений (прав доступа)
- Чтение
Авторизовать приложение Запретить
Мы видим что ”Thedropletbook App” запрашивает разрешение на доступ к чтению аккаунта “[email protected] ”.
Шаг 3: Браузер получает маркер доступа с переадресацией URI
Шаг 4: Браузер следует за переадресацией URI
Браузер следует за переадресацией URI, но при этом сохраняет маркер доступа.
Шаг 5: Приложение отправляет маркер доступа скрипту извлечения
Приложение возвращает страницу, которая содержит скрипт, который может извлекать маркер доступа, из целого URI передаресации, который сохранил браузер.
Шаг 6: Маркер доступа передаётся в приложение
Браузер запускает предоставленный скрипт и передаёт извлечённый маркер доступа приложению.
Примечание : DigitalOcean не поддерживает в данное время тип неявного предоставления, так что ссылка указывает на воображаемый сервер авторизации на «oauth.example.com».
С типом предоставления владельца ресурса пароля учётных данных, пользователь предоставляет свои учётные данные сервиса (имя пользователя и пароль) напрямую приложению, которое использует учетные данные для получения маркера доступа от сервиса. Этот тип предоставления должна быть активизированным на сервере авторизации, только если другие потоки не являются жизнеспособными. Также он должен использоваться, если приложение является доверенным для пользователя (например, если оно принадлежит сервису или операционной системе компьютера).
Поток пароля учётных данных
После того как пользователь передал свои учётные данные приложению, после этого оно должно запросить маркер доступа у сервера авторизации. POST запрос может выглядеть как-то так:
Если учётные данные пользователя прошли проверку, сервер авторизации возвращает маркер доступа приложению. Теперь приложение авторизовано!
Примечание : DigitalOcean не поддерживает в данное время тип предоставления пароля учётных данных, так что ссылка указывает на воображаемый сервер авторизации на «oauth.example.com».
Тип предоставления учётных данных клиента предоставляет приложению способ доступа к своему личному аккаунту сервиса. Примеры того, когда это может быть полезным, если приложение хочет обновить своё зарегистрированное описание или URI переадресации, или обратиться к другим данным сохранённым в аккаунте сервиса через АПИ.
Поток учётных данных клиента
Приложение запрашивает маркер доступа отправляя свои учётные данные, свои идентификатор клиента и секретный код клиента, серверу авторизации. Пример POST запроса может выглядеть следующим образом:
Если учётные данные клиента прошли проверку, сервер авторизации возвращает приложению маркер доступа. С этого момента приложению разрешено использовать её собственный аккаунт!
Примечание : DigitalOcean не поддерживает в данное время тип предоставления учётных данных клиента, так что ссылка указывает на воображаемый сервер авторизации на «oauth.example.com».
Пример использования маркера доступа
Как только у приложения появился маркер доступа, оно может использовать маркер для доступа к акаунту пользователя через АПИ, с ограничениями по доступу, пока маркер не истечёт или не будет отменён.
Вот пример АПИ запроса использующего curl . Обратите внимание на то, что он включает маркер доступа:
curl -X POST -H «Authorization: Bearer ACCESS_TOKEN» «https://api.digitalocean.com/v2/$OBJECT» ;
Предполагая, что маркер доступа действителен, АПИ будет обрабатывать запрос в соответствии с своими техническими условиями. Если срок маркера доступа истёк или в противном случае недействителен, АПИ вернёт ошибку “неверный_запрос”.
Поток маркера обновления
После того как срок маркера доступа истёк, использование его для совершения запрос к API приведет к ошибке «Недействительный маркер». На этой стадии, если маркер обновления был включён в запрос, когда исходный маркер доступа был выпущен, он может быть использован для запроса свежего маркера доступа у сервера авторизации. Вот пример POST запроса, использующего маркер обновления для получения нового маркера доступа:
На этом мы завершает руководство по OAuth 2. Теперь вы должны иметь хорошее представление о том, как работает OAuth 2 и когда конкретный поток авторизации следует использовать.
Если вы хотите узнать больше об OAuth 2, проверьте эти полезные ресурсы:
Переходим по ссылке http://api.mail.ru/sites/my/add и регистрируем наш сайт. Далее скачиваем и заливаем на ftp файл receiver.html, который нужен для верификации нашего сайта.
После регистрации нам выдадут 3 параметра:
Нас будет интересовать только ID и Секретный ключ (Приватный ключ нужен для модели клиент-сервер). Сохраним их в конфигурационном файле нашего скрипта под следующими именами.
$APP_ID; $APP_SECRET;
Для получения Code нужно обратиться по адресу connect.mail.ru/oauth/authorize , передав ему $_GET параметры:
Для удобства разделим логику генерации ссылки на получение code и его обработки:
example.com/login.php - генерируем ссылку для получения code (по-сути ссылка для авторизации).
example.com/auth.php - обработка code.
Итоговый запрос будет выглядеть так:
$redirect_uri = urlencode("http://example.com/auth.php"); $login_url = "https://connect.mail.ru/oauth/authorize?client_id={$APP_ID}&response_type=code&redirect_uri={$redirect_uri}";
Перейдя по этому адресу неавторизованный на Mail.ru пользователь увидит:
Если пользователь авторизован на Mail.ru, то он увидит такое же окно, но без ввода логина и пароля.
Теперь у пользователя 2 варианта действий: разрешить и запретить. Запретив, пользователь будет перенаправлен на страницу указанную в redirect_uri
с указанием ошибки.
Если всё прошло как надо и пользователь разрешил сайту доступ к своим данным, то пользователь будет перенаправлен на страницу redirect_uri
(http://example.com/auth.php), с $_GET параметром code.
Сохраним его под именем
$APP_CODE;
Для этого надо обратиться по адресу connect.mail.ru/oauth/token , передав ему параметры:
Все параметры обязательтны. redirect_uri должен точно совпадать с тем, который мы использовали на 2-ом шаге.
Запрос на получения token может быть выполнен только через POST запрос, поэтому cURL в помощь:
$ch = curl_init(); $url = "https://connect.mail.ru/oauth/token"; $fields = Array("client_id" => $APP_ID, "client_secret" => $APP_SECRET, "grant_type" => "authorization_code", "code" => $APP_CODE, "redirect_uri" => urlencode(redirect_uri)); foreach($fields as $key => $value){ $fields_string .= $key . "=" . $value . "&"; } rtrim($fields_string, "&"); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); $result = curl_exec($ch); curl_close($ch); $arr = json_decode($result, true); //или $arr = (array) json_decode($result). Кстати кто-нибудь знает, есть ли разница? $token = $arr["access_token"]; $uid = $arr["x_mailru_vid"];
После получения token
и uid
сайт получает долгожданный доступ к API Mail.ru по адресу www.appsmail.ru/platform/api
.
Но не всё так просто, каждый запрос к API должен быть подписан. Подпись (в нашем случае) представляет собой хэш, рассчитанный по алгоритму md5 из отсортированной в алфавитном порядке строки из передаваемых API параметров без разделителя &
и Секретного ключа
.
Например:
Md5("app_id=423004method=friends.getsession_key=be6ef89965d58e56decdfacb9b62bdaa" . $APP_SECRET);
Mail.ru предусматривает 2 варианта подписи: клиент-сервер и сервер-сервер. Отличие заключается в большей безопасности 2-го подхода. Его мы и будем использовать. Для этого в запросе к API надо указывать secure=1 .
Выполним запрос на получение анкетной информации пользователя Mail.ru, воспользовавшись методом users.getInfo .
$request_params = Array("app_id" => $APP_ID, "uids" => $uid, "method" => "users.getInfo", "secure" => 1, "session_key" => $token); //Параметры обязательно должны быть отсортированы в алфавитном порядке ksort($request_params); $params = ""; foreach ($request_params as $key => $value) { $params .= "$key=$value"; } //В модели сервер-сервер подпись выглядит так $sig = md5($params . $APP_SECRET); //Формируем запрос $url = "http://www.appsmail.ru/platform/api?method=users.getInfo&app_id={$APP_ID}&session_key={$token}&sig={$sig}&uids={$uid}&secure=1"; $response = file_get_contents($url); $info = (array) json_decode($response); $info = $info; //весь результат print_r($info);
Вот и всё. Таким образом мы получили необходимые нам данные для занесения пользователя в базу данных. Весь дальнейший процесс уже неоднократно был описан, например . Так что не вижу смысла его описывать.
PROFIT!!1 Всем добра. Если статья окажется интересной, то могу так же разобрать процесс серверной oAuth 2.0 авторизации для Vkontakte и Facebook.
Существует множество способов распространения вредоносного спама во ВКонтакте. Но вредители не дремлют, в их головы приходят все больше интересных идей. И оказалась как никак кстати. Мошенники научились пользоваться им для обхода страницы предупреждения о вредоносных сайтах.
А все началось с того, что однажды на моей стене появилось такое сообщение:
Из любопытства перешел по ссылке и попал на очередной фишинговый сайт. Но мне показалась странной сама ссылка, она имела вид (половина символов в ASCII):
vkontakte.ru/away.php ?to
=http%3A%2F%2FApi.vKontakte.Ru%2F%2Fo%2561u%2574%…
Что означает каждый из параметров:
В этом и заключается весь смысл обхода блек-листа вредоносных сайтов ВКонтакте. Появляется только алерт о переходе на api.vk.com. И в результате перехода мы прямиком попадаем на фишинг сайт, который имеется в черном списке. При переходе по ссылке vkontakte.ru/away.php?to=vgostivk.dyndns**:
Как оказалось, приложение, якобы требующее авторизацию висело на взломанном пользователе:
Да и сам фишинг сайт был устроен довольно интересно. Дизайн по обычаю был контактовский и предлагал авторизоваться. Я прошел авторизацию через рандомные почту и пароль, фейк прекрасно проглотил. Дальше было еще интересней, на главной появилась новость от «Павла Дурова»:
После нажатия на кнопку «Создать персональный счетчик», последовал прекрасный прогресс-бар. Затем было предложено указать свой номер и отправить sms:
По идее после успешной «активации» должно было перекинуть на страницу activ.php, но я не смог попасть туда. Выдержки из JS скриптов фишинг сайта:
...
if (req.status == 200) {
// если статус 200 (ОК) - выдать ответ пользователю
if (req.responseText == "ok" ) {
//statusElem.innerHTML = "Все гуд!";
get_activation();
}
if (req.responseText == "not" ) {statusElem.innerHTML = "Неверный код активации" ;}
//statusElem.innerHTML = "Ответ сервера: "+req.responseText;
...
function get_activation() {
document .location="activ.php" ;
}* This source code was highlighted with Source Code Highlighter .
Популярный протокол, который позволяет социальным сервисам интегрироваться между собой и дает безопасный способ обмена персональной информацией. OAuth может связать между собой 2 сервиса, каждый из которых имеет свою пользовательскую базу - именно их я в данном случае называю «социальными». Когда начинаешь работать с OAuth, первое ощущение - что протокол весьма сложен и избыточен. В этой статье я попытаюсь объяснить основы OAuth человеческим языком.
Милицейская аналогияПредставьте, что вы - сотрудник Уголовного розыска, ищущий концы в деле о краже WebMoney за 1973-й год. Договоримся о терминах:
|
Во-первых, напишем саму форму импорта контактов с GMail:Далее попросим разработчиков GMail сделать так, чтобы при переходе пользователя по URI /auth.php ему бы выдавалась форма авторизации (в нашем веломире GMail написан на PHP). После успешного ввода пароля пользователь должен редиректиться на сайт, чей URL указан в параметре retpath. Также дополнительно в URL должен передаваться некоторый секретный ключ, который уже можно использовать для доступа к API GMail.
Итак, после ввода пароля пользователь будет возвращаться к нам на сайт по следующему адресу:А мы из скрипта /import.php обратимся к API GMail, передадим в него ключ Y49xdN0Zo2B5v0RR и загрузим контакты:Ну что же, давайте теперь считать грабли (потому что шишки считать будет уже поздно).
Итак, если Consumer и Provider каким-то образом договорятся между собой о Shared Secret, они могут открыто обмениваться в URL соответствующими ключами (Key), не опасаясь, что перехват этих ключей будет опасен. Но как защитить URL с Key от подделки?
Аналогично, цифровая подпись добавляется к некоторому блоку данных, удостоверяя: тот, кто сформировал эти данные, не выдает себя за другого. Цифровая подпись не шифрует документ, она лишь гарантирует его подлинность! Поставить подпись позволяет тот самый Shared Secret, который известен получателю и отправителю, но более никому.
Как это работает? Пусть наш $sharedSecret = 529AeGWg, и мы сообщили его шепотом на ухо принимающей стороне. Мы хотим передать сообщение «Мой телефон 1234567» с гарантированной защитой от фальсификации злоумышленником.
Вы можете вставить данный виджет на любой PHP-сайт, просто скопировав его код и подправив верстку. Выводятся все твиты с сервиса РуТвит , помеченные указанным хэш-тэгом, а также имеется возможность добавлять новые твиты (тут-то как раз и задействуется OAuth). Виджет использует API и OAuth-авторизацию РуТвита, которые, кстати говоря, совпадают со стандартом API Twitter-а.Вы можете запустить этот скрипт на своем тестовом сервере. Для этого нужно выполнить три действия:
После регистрации приложения вам выдается 5 параметров, которые требуются для работы с OAuth. Вот как они могут выглядеть:
Здесь Consumer key и Consumer secret - это своеобразные «логин + пароль» вашего приложения (помните выше разговор о токенах? это как раз один из них). Напомню, что Consumer secret - это Shared Secret, известный только отправителю и получателю, но никому больше. Остальные 3 значения задают служебные URL, смысл которых мы сейчас рассмотрим.
И мы вскрыли ряд проблем с безопасностью, что наводит на мысль: вызовов должно быть больше. Так и происходит в OAuth: добавляются еще промежуточные запросы от скрипта Consumer-а к Provider-у, оперирующие токенами. Давайте их рассмотрим.
Листинг 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)?>
}?>
|
После того, как пользователь выдаст права, происходит редирект на стандартную страницу-заглушку, для 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 и использовать его для обращения к защищенным ресурсам.