我正在使用Django Rest Framework构建API。稍后,iOS和Android设备应该可以使用此API。我希望允许我的用户使用Facebook和Google等oauth2提供程序进行注册。在这种情况下,他们根本不需要在我的平台上创建帐户。但是,即使没有Facebook / Google帐户,用户也应该能够注册,为此我使用django-oauth-toolkit,因此我有自己的oauth2提供程序。
对于外部提供商,我正在使用python-social-auth,它可以很好地工作并自动创建用户对象。
我希望客户端使用令牌来进行身份验证,这对于使用我的提供程序注册的用户非常有效(django-oauth-toolkit为Django REST Framework提供身份验证方案和权限类)。
然而,python-social-auth仅实现基于会话的身份验证,因此无法直接为通过外部oauth2提供程序注册的用户进行身份验证,也就无法在其名义上进行身份验证的API请求。
如果我使用由django-oauth-toolkit生成的access_token,则像这样进行请求是可以的:
curl -v -H "Authorization: Bearer <token_generated_by_django-oauth-toolkit>" http://localhost:8000/api/
然而,以下方法不起作用,因为Django REST Framework没有相应的身份验证方案,并且python-social-auth提供的AUTHENTICATION_BACKENDS仅适用于基于会话的身份验证:
curl -v -H "Authorization: Bearer <token_stored_by_python-social-auth>" http://localhost:8000/api/
在使用python-social-auth进行认证后,使用Django REST Framework提供的可浏览API功能完全正常,但是没有会话cookie的API调用不起作用。
我想知道解决这个问题的最佳方法是什么。我认为,我基本上有两个选择:
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请求身份验证。我可以通过编写自定义后端并使用register_by_access_token将我的用户添加到python-social-auth中。但是,由于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对每个无状态API请求都执行整个oauth2流程,并对存储在DB中的数据进行检查,这并不适合查询,因为它以JSON格式存储(但我可以使用UserSocialAuth.objects.get(extra_data__contains=))。同时,我还必须注意验证访问令牌的范围,并使用它们来检查权限,django-oauth-toolkit已经处理了此问题(TokenHasScope
,required_scopes
等)。
目前,我倾向于使用选项A,因为django-oauth-toolkit与Django Rest Framework有很好的集成,并且我可以从框架中获得所需的所有内容。唯一的缺点是我必须将python-social-auth检索到的访问令牌“注入”到django-oauth-toolkit的AccessToken模型中,这种方式感觉有些不对,但可能是最简单的方法。
是否有人反对这样做或以不同的方式解决了相同的问题?我是否遗漏了任何明显的事情并使生活比必要困难?如果有人已经将django-oauth-toolkit与python-social-auth和外部oauth2提供程序集成,我将非常感激一些指针或意见。
python-social-auth
。 - jeverling