Новости Django Social Auth — 2

30 апреля 2011

Предыдущие новости см. здесь.

В коммите добавлены:

  1. Поддержка OAuth 2.0 для ВКонтакте
  2. Поддержка OAuth 2.0 для Mail.ru
  3. Решена проблема с return_to. Одна строчка правок потребовала усилий со стороны четырех человек, вот как бывает.

Следующий коммит будет не раньше середины мая: уезжаю в отпуск.

Новости Django Social Auth

19 апреля 2011

В продолжение статьи «Авторизация в социальных сетях для Django».

Основная ветка проекта развивается довольно интенсивно, добавилась поддержка LinkedIn, Google OAuth2, тесты и большое количество мелких, но полезных фитюлечек, вроде автоматического ассоциирования пользователя по e-mail.

Замечена интересная особенность Google OpenID. Если ваш сайт поддерживает «сквозную» авторизацию на поддоменах и вам принципиально, чтобы человек, авторизовавшийся в одном поддомене, мог продолжать работать без авторизации и в другом, я рекомендую воспользоваться Google OAuth. Фишка в том, что Google OpenID выдает разные id пользователя для разных поддоменов одного и того же сайта. Так как библиотека не может определить, что пользователь, который пришел на поддомен ААА, уже был зарегистрирован в поддомене БББ, в результате создается новая учетная запись. У OAuth такой проблемы нет, зато есть два плюса: вы гарантированно получаете e-mail пользователя и вам не нужно регистрировать свое приложение, как в OAuth 2.0.

Обнаружена ошибка в библиотеке Python-OpenID, которая выдает довольно странную диагностику: OpenID authentication failed: return_to does not match return URL, при этом URL’ы совпадают. Обсуждение находится здесь, авторам библиотеки сообщение отправлено, ждем, когда поправят.

В моем форке два изменения:

  1. Для авторизации на Yandex теперь не обязательно указывать имя пользователя. Если оно не задано, то используются возможности OpenID 2.0, сервер с библиотекой договариваются сами и, когда надо, задают пользователю необходимые вопросы. Спасибо Ивану Сагалаеву за подсказку (детали обсуждения здесь).
  2. Добавлен backend для авторизации на Одноклассниках с использованием OAuth 2.0. По умолчанию запрашиваемый scope минимален, этого хватает для авторизации, а пользователю не нужно мучительно размышлять, давать ли доступ к своей стене, e-mail и пр.

Внимание, вопрос: поддержку какого именно сервиса авторизации вам бы хотелось увидеть следующей: ВКонтакте через OAuth 2.0 или Mail.ru?

Авторизация в социальных сетях для Django

22 января 2011

Зачем

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

  1. Кроме крупных мировых сетей хотелось также работать с LiveJournal, Yandex и ВКонтакте.
  2. Нужна была возможность контролировать действия системы после успешной авторизации, то есть управлять процессом обработки полученной от сервиса информации о пользователях.

Я остановился на https://github.com/omab/django-social-auth: просмотрев исходники, я увидел, что их немного, а написано все понятно. Изначально библиотека поддерживала Facebook, Twitter, Google, OpenID и OpenAuth и процесс работы с БД был немного не такой, как хотелось бы. Форка было не избежать, правда, в скором времени мы с автором исходной библиотеки немного подружились, в результате чего большая часть моих изменений ушла в основную ветку, а в моем форке остались только Yandex и ВКонтакте.

После всех изменений результат мне пришелся очень по сердцу: в случае необходимости можно просто добавлять движки для новых сервисов, а работа с БД достаточно проста, чтобы не слишком о ней думать. Также вне зависимости от того, как происходит авторизация (о, иногда это достаточно замысловатый процесс, поверьте мне на слово), работа с данными пользователя унифицирована, что тоже очень удобно.

Как это работает

Для каждого сервиса есть два класса – auth и backend. Напрямую вы с ними работаете, только если вам нужно добавить свой сервис, в противном случае вы просто вызываете метод auth библиотеки и скармливаете ему имя сервиса и нужные параметры. После того как авторизация завершена, вызывается метод complete. Что происходит внутри, описано ниже.

1. Класс auth отвечает за авторизацию на сайте сервиса и убеждается, что все прошло успешно (см. рисунок).

2. Класс backend отвечает за авторизацию собственно в вашем приложении (через стандартный authenticate) и за работу с таблицей пользователей на основании тех данных, которыми сервис соизволил с вами поделиться. Некоторые сервисы (не будем показывать пальцем, хотя это был ЖЖ) не дают никакой информации, кроме «наш человек/не наш человек».

Для backend можно задавать ту модель пользователя, которая используется в вашем приложении, если вы не используете стандартный класс User. В менеджере этой модели можно, например, принимать решение, когда создавать нового пользователя, а когда – использовать уже имеющегося.

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

При успешной авторизации в специальной таблице сохраняется информация о том, какой пользователь связан с какими (1:N) сервисами авторизации. Для привязки уже залогиненного пользователя используются методы библиотеки associate.

«Просто, понятно, легко запомнить», как говорил капитан Д. Воробей.

Что брать и на что обратить внимание

Итак, мой форк здесь: https://github.com/krvss/django-social-auth

В существующую архитектуру довольно легко вписался ВКонтакте – его backend сейчас, кроме авторизации, проверяет также «подпись» данных, чтобы чего не вышло.

Когда вы, авторизуясь на Yandex через OpenId, ставите галочку «передать дополнительные параметры», в Django почему-то возникает нарушение целостности или потеря csrf-информации. Чтобы не возникала ошибка, можно указать свою функцию для завершения авторизации (параметр SOCIAL_AUTH_COMPLETE_URL_NAME), которая будет отличаться только наличием декоратора csrf_exempt_view и состоять из вызова social_auth.complete.

Upd: Причины такого поведения Yandex объясняются в комментариях к этой записи.

Новые записи →