Я создаю API, используя Django Rest Framework. Позже этот API будет потребляться устройствами iOS и Android. Я хочу разрешить моим пользователям регистрироваться с oauth2-провайдерами, такими как Facebook и Google. В этом случае им не нужно создавать учетную запись на моей платформе вообще. Но пользователи также должны иметь возможность регистрироваться, если у вас нет учетной записи Facebook/Google, для которой я использую django-oauth-toolkit, поэтому у меня есть собственный поставщик oauth2.
Для внешних поставщиков я использую python-social-auth, который отлично работает и автоматически создает пользовательские объекты.
Я хочу, чтобы клиенты аутентифицировались с помощью токенов-носителей, что отлично подходит для пользователей, которые подписались с моим поставщиком (django-oauth-toolkit предоставляет схему аутентификации и классы разрешений для Django REST Framework).
Однако python-social-auth реализует только аутентификацию на основе сеанса, поэтому нет простого способа сделать аутентифицированные запросы API от имени пользователей, зарегистрированных внешним поставщиком oauth2.
Если я использую access_token, созданный django-oauth-toolkit, выполнение такого запроса работает:
curl -v -H "Authorization: Bearer <token_generated_by_django-oauth-toolkit>" http://localhost:8000/api/
Однако следующее не работает, поскольку нет соответствующей схемы аутентификации для Django REST Framework, а AUTHENTICATION_BACKENDS, предоставленные python-social-auth, работают только для проверки на основе сеанса:
curl -v -H "Authorization: Bearer <token_stored_by_python-social-auth>" http://localhost:8000/api/
Использование API-интерфейса для просмотра, предоставляемого Django REST Framework после аутентификации с помощью python-social-auth, очень просто, только API-вызовы без файла cookie сеанса не работают.
Мне интересно, какой лучший подход для этой проблемы. Как я его вижу, у меня есть в основном два варианта:
A: Когда пользователь подписывается с внешним поставщиком oauth2 (обрабатывается python-social-auth), подключитесь к процессу для создания oauth2_provider.models.AccessToken и продолжайте использовать 'oauth2_provider.ext.rest_framework.OAuth2Authentication'
, теперь аутентифицируя также пользователей, которые зарегистрированный у внешнего провайдера. Этот подход предлагается здесь:
https://groups.google.com/d/msg/django-rest-framework/ACKx1kY7kZM/YPWFA2DP9LwJ
B: Использовать python-social-auth для аутентификации запроса API. Я мог бы завести своих пользователей в python-social-auth, написав собственный бэкэнд и используя register_by_access_token. Однако, поскольку вызовы API не могут использовать сеансы Django, это означало бы, что мне пришлось бы написать схему аутентификации для Django Rest Framework, которая использует данные, хранящиеся в python-social-auth. Некоторые указатели на то, как это сделать, можно найти здесь:
http://psa.matiasaguirre.net/docs/use_cases.html#signup-by-oauth-access-token
http://blog.wizer.fr/2013/11/angularjs-facebook-with-a-django-rest-api/
http://cbdev.blogspot.it/2014/02/facebook-login-with-angularjs-django.html
Однако, как я понимаю, python-social-auth проверяет только токен при регистрации и позже полагается на сеанс Django. Это означало бы, что мне нужно было бы найти способ предотвратить выполнение python-social-auth всего потока oauth2 для каждого запроса API без состояния и скорее проверить данные, хранящиеся в БД, которые на самом деле не оптимизированы для запросов, поскольку это сохраненный как JSON (я мог бы использовать UserSocialAuth.objects.get(extra_data__contains =), хотя).
Я также должен был бы позаботиться о проверке областей доступа к токену и использовать их для проверки разрешений, что уже делает django-oauth-toolkit (TokenHasScope
, required_scopes
и т.д.).
В настоящий момент я склоняюсь к использованию опции A, поскольку django-oauth-toolkit обеспечивает хорошую интеграцию с Django Rest Framework, и я получаю все, что мне нужно из коробки. Единственным недостатком является то, что я должен "вводить" access_tokens, полученный python-social-auth, в модель Django-oauth-инструментария AccessToken, которая как-то кажется неправильной, но, вероятно, будет самым простым способом.
Есть ли у кого-нибудь какие-либо возражения против этого или, возможно, решить эту проблему по-другому? Упускаю ли я что-то очевидное и делаю свою жизнь труднее, чем необходимо? Если кто-то уже интегрировал django-oauth-toolkit с python-social-auth и внешними поставщиками oauth2, я был бы очень благодарен за некоторые указания или мнения.