Django Social Auth: Авторизация на Яндекс через OAuth2
Понедельник, как говорится, начинается в субботу — праздники дали возможность немного поработать над своими проектами. Добавлен backend для авторизации на Яндекс через OAuth2. Особенности/ограничения:
- Нельзя указывать права доступа в настройках приложения. Права доступа задаются для разных сервисов Яндекса при регистрации приложения. Там же прописывается redirect_uri.
- В настройке YANDEX_OAUTH2_API_URL указывается URL того сервиса, из которого вы хотите получать информацию о пользователе. Проверено и работают 2 сервиса: Я.ru, url=’https://api-yaru.yandex.ru/me/’ и Мой Круг, url=’http://api.moikrug.ru/v1/my/’. Не получилось проверить Яндекс.Фотки (url=’http://api-fotki.yandex.ru/api/me/’), как я не пытался все время возникала 500 Internal Server Error. Возможно, в праздники идет какой-то апгрейт.
Буду благодарен за обратную связь по работе backend’a.
Обновление от 19.01
Служба поддержки Яндекса помогла разобраться с проблемой вызова API Фоток, за что я ей очень благодарен. Я переделал backend чтобы этот API можно было использовать в будущем, на сегодняшний день его использовать пока нельзя. Причина в том, что ответ от me не содержит id пользователя в системе (совсем) и login пользователя (неявно он есть в url альбомов), писать специально для Фоток частный случай обработки не очень хочется, надеюсь это исправится со временем.
Обновление 2
Код получения аватаров пользователей обновлен для поддержки Яндекса.
Ответы на: Django Social Auth: Авторизация на Яндекс через OAuth2
bashmish пишет:
19 января, 2012
Зашел сюда чтобы попросить 🙂 на Гитхабе написать не получается личное сообщение
У omab был пофиксен достаточно серьезный баг ( https://github.com/omab/django-social-auth/pull/219 ), хочется чтобы он побыстрее попал в мастер твоего репозитария. Заранее спасибо 🙂
PS: спасибо за новый бекенд и вообще за постоянную работу над проектом!
krvss пишет:
19 января, 2012
Сегодня будет, я раз в 2 недели делаю merge.
elmit пишет:
16 февраля, 2012
Привет. Очень нужна функциональность прерывания пайплайна, которая недавно появилась в «ванильной» версии django-social-auth. Можно ли как-то ускорить merge твоей версии?
krvss пишет:
16 февраля, 2012
Сегодня как раз день merge 🙂 Недавно сделал его.
elmit пишет:
16 февраля, 2012
Спасибо
elmit пишет:
16 февраля, 2012
Спасибо
softshape пишет:
16 марта, 2012
А есть ли где-то, кроме conceptor.ru, реализация клиентской части с всплывающими окнами? То, что сейчас лежит в examples, открывает сайт сервиса в этом же окне. Это категорически неправильно. На conceptor’е — правильно, но с использованием jQuery UI (функция dialog()) что м…. правильно, но не совсем.
krvss пишет:
16 марта, 2012
К сожалению пользователи редко делятся со мной своими проектами. Наверняка я знаю один, но тот не использует всплывающих окон. Интересующимся как сделать через окна обычно достаточно реализации conceptor’а.
softshape пишет:
19 марта, 2012
В conceptor’е очень много оформительского кода, завязанного на jQuery UI. Открыть новое окно само по себе несложно, это ровно одна функция window.open:
$(document).ready(function() {
$(‘.openid_list a’).click(function (e) {
window.open($(this).attr(‘href’), ‘login’);
return false;
});
});
Но мне пока непонятно, как отследить момент завершения авторизации в этом окне.
krvss пишет:
19 марта, 2012
Про открытие окна я в курсе 🙂
Момент завершения авторизации определяется так:
1. Во всплывающем окне вызывается url, который обозначает успех авторизации
2. В нем грузится специальный view со скриптом
3. Скрипт через window.parent перегружает родительскую страницу
Думал сделать поинтеллектуальнее — ну там можно типа вызвать какую-то умную функцию которая что-то там у родителя перерисует, но это потянуло в нашем случае прилично кода, а выигрыш был неочевиден. Остановились на простом reload.
softshape пишет:
19 марта, 2012
Прилично кода?
window.opener.someSmartFunction(‘success’); window.close();
Это все, что нужно. Мы, по крайней мере, так будем делать. Дело в том, что на основной странице в это время может быть, например, текст свежего комментария, который потеряется при тупом релоаде. Да, релоад можно сделать, но перед этим вызвать someSmartFunction(‘success’), чтобы она сделала какую-то подготовку страницы — форму с комментарием сабмитила, еще что-нибудь.
krvss пишет:
19 марта, 2012
Ну, как вы будете делать — это ваша боль 🙂 Непонятно, зачем ты меня спрашиваешь о том, что сам знаешь. И зачем рассказываешь мне то, что я сам знаю 🙂
softshape пишет:
19 марта, 2012
Чтобы сэкономить немного времени тем потомкам, что будут читать нашу переписку спустя какое-то время в попытках решить аналогичную задачу. Всем, кто меня слышит! Не смотрите на conceptor.ru, он вам не поможет! Вам нужен window.open() в начале и window.opener.myFunction() в конце. И все.
ur001 пишет:
3 апреля, 2012
Яндексу нужно обязательно указать redirect_uri, причём только один.
Как тогда быть с 2-мя url-ами complete// и associate/complete//?
ur001 пишет:
3 апреля, 2012
Съелось парсером <backend>
krvss пишет:
3 апреля, 2012
да, проблема; думаю как решить.
ur001 пишет:
4 апреля, 2012
Эта проблема, кстати, актуальна и для других провайдеров. Но во большинстве случаев она решается. Например в Foursquare можно указать в качестве callback_uri только чать (например http://домен/soacial_auth/), и это работает для http://домен/soacial_auth/complete/foursquare/ и http://домен/soacial_auth/associate /complete/foursquare/
Единственным верным решением я вижу создание единого callback_uri и дальнейшее разруливание действий на основе записи cookies, сессии и т.п.
Кстати, помимо прочего есть сложность с привязкой пользователя по email. associate_by_email не может определить какое действие происходит — auth или associate. Получается я не могу привязать к существующему аккаунту провайдер, если уже зарегистрирован пользователь с совпадающим email-ом. Например я логинюсь под Яндексом-ом, забыв что этот аккаунт ещё не привязывал и содзаётся новый пользователь. Единственный способ перепривязать его — это отвязать Яндекс от нового аккаунта, залогиниться под старым и выполнить привязку. Но associate_by_email не даст этого сделать пока я не сменю email в аккаунте созанном через Яндекс.
krvss пишет:
4 апреля, 2012
Да, я тоже не смог придумать другой вариант. Задание части uri было бы наилучшим вариантом, и тут Яндекс перегнул с безопасностью на мой взгляд. Вообще с ними можно попробовать пообщаться, там хорошая поддержка.
Столкнулся тоже с этой проблемой — хуже всего, что для старой записи уже могут быть какие-то действия, и потом непонятно что с ней делать: мержить или оставить как была? Так как жалоб не поступало оставил существующую реализацию.
m0n61an пишет:
24 сентября, 2012
Столкнулся с проблемой при настройке Yandex OAuth. На Яндексе указываю Callback URI: http://***/auth/oauthcomplete/yandex-oauth2/
При попытки логина по ссылке http://***/auth/oauthlogin/yandex-oauth2/ Яндекс выдает «Ошибка 400: redirect_uri_mismatch». Причиной является GET-параметр redirect_state. При его отсутствии ошибка исчезает.
Для рабочей авторизации добавил параметр REDIRECT_STATE=False в класс YaruAuth: http://pastebin.com/HUSa6f1Y
Подскажите, как избежать данной ошибки как-то более красиво и не править чужой код?
krvss пишет:
25 сентября, 2012
Посмотрел — дело не в REDIRECT_STATE, а в том, что он неправильно добавляется к URL.
Вот как выглядит правильная ссылка:
https://oauth.yandex.ru/authorize?state=g85M3M8ri5JdUJuAyFARY15PKAYw5ZAd&redirect_uri=http%3A%2F%2Fmyproj.ru%2Fcomplete%2Fyandex-oauth2%2F&redirect_state=Dg85M3M8ri5JdUJuAyFARY15PKAYw5ZAd&response_type=code&client_id=d782fbbb80af41ed869811b9af34ac2c
А вот как генерируется сейчас:
https://oauth.yandex.ru/authorize?state=GFX54CVNAuDiHkVVBnzGU38myi1OSPkt&redirect_uri=http%3A%2F%2Fmyproj.ru%2Fcomplete%2Fyandex-oauth2%2F%3Fredirect_state%3DGFX54CVNAuDiHkVVBnzGU38myi1OSPkt&response_type=code&client_id=d782fbbb80af41ed869811b9af34ac2c
То есть во-первых, перед redirect_state стоит не «=» а «%3F», а во вторых после redirect_state стоит не «=» а «%3D». Соответственно, Яндекс приписывает redirect_state к redirect_uri и справедливо ругается на то, что redirect_uri совсем не тот, что должен.
Вообще в коде добавление происходит через функцию url_add_parameters в модуле utils. Автор этой функции Матиас, так что я бы посоветовал написать ему issue вот тут: https://github.com/omab/django-social-auth/issues
Либо сделать форк и поправить самому 🙂 Я поправить не успею — послезавтра в отпуск, дел невпроворот. Но с другой стороны это не наш баг 🙂
m0n61an пишет:
1 октября, 2012
Я все-таки настою на своём!
Из social_auth/backends/__init__.py:686
Store state in session for further request validation. The state value is passed as state parameter (as specified in OAuth2 spec), but also added to redirect_uri, that way we can still verify the request if the provider doesn’t implement the state parameter.
Отсюда я делаю вывод, что ссылка создается правильно, так как redirect_state нам нужно передать далее в callback uri. И ошибка все-таки в реализации YaruAuth, так как там недостает параметра REDIRECT_STATE=False
krvss пишет:
2 октября, 2012
Я вижу, что правка уже в основной ветке. Ну, так тому и быть 🙂
YaruAuth не мой бэкэнд, посмотрел еще по коду — понял, что в первый раз не заметил, что redirect_state передается внутрь redirect_uri для обратного вызова после авторизации, что меняет дело.