无法设置 django-oauth-toolkit 身份验证
Could not setup django-oauth-toolkit authentication
我将限制我的工作 rest_framework.views.APIView
继承 class,仅对经过身份验证的用户可见。
我做了这些修改:
- 已将
authentication_classes
和 permission_classes
添加到我的 class:
class TestView(APIView):
authentication_classes = (OAuth2Authentication,)
permission_classes = (IsAuthenticated,)
return Response("Hey there...")
- 从 django-oauth-toolkit 得到一个 access_token:
curl -XPOST "http://172.18.0.1:8000/oauth2/token/" \
-d 'grant_type=client_credentials&client_id=MY-CLIENT-ID&client_secret=MY-CLIENT-SECRET'
{"access_token": "Haje1ZTrc7VH4rRkTbJCIkX5u83Tm6", "expires_in": 36000, "token_type": "Bearer", "scope": "read write groups"}
- 尝试在不设置
access_token
的情况下请求视图:
curl -XGET "http://172.18.0.1:8000/api/v1/test/"
{"detail":"Authentication credentials were not provided."}
- 尝试使用
access_token
的新请求:
curl -XGET "http://172.18.0.1:8000/api/v1/test/" \
-H "Authorization: Bearer Haje1ZTrc7VH4rRkTbJCIkX5u83Tm6"
{"detail":"You do not have permission to perform this action."}
我还应该做些什么来启用 access_token 身份验证吗?
注意:我已经在环境中安装了这些库:
Django==2.2.17
djangorestframework==3.12.2
django-oauth-toolkit==1.3.3
注2:忘记说rest_framework
和oauth2_provider
已经添加到INSTALLED_APPS.
重要编辑:
此问题仅在使用“客户端凭据授予”进行身份验证时存在。在下面检查我自己的答案。
尝试在 Django rest 框架中使用 djoser 进行身份验证
最后我发现 OAuth2Authentication
不通过其 client_credential 验证用户(接受 username/password 与 grant_type= 密码对)。所以我写了这个自定义验证器。希望它能帮助其他遇到同样问题的人。
from oauth2_provider.contrib.rest_framework import OAuth2Authentication
from oauth2_provider.models import Application
class OAuth2ClientCredentialAuthentication(OAuth2Authentication):
"""
OAuth2Authentication doesn't allows credentials to belong to an application (client).
This override authenticates server-to-server requests, using client_credential authentication.
"""
def authenticate(self, request):
authentication = super().authenticate(request)
if not authentication is None:
user, access_token = authentication
if self._grant_type_is_client_credentials(access_token):
authentication = access_token.application.user, access_token
return authentication
def _grant_type_is_client_credentials(self, access_token):
return access_token.application.authorization_grant_type == Application.GRANT_CLIENT_CREDENTIALS
我将限制我的工作 rest_framework.views.APIView
继承 class,仅对经过身份验证的用户可见。
我做了这些修改:
- 已将
authentication_classes
和permission_classes
添加到我的 class:
class TestView(APIView):
authentication_classes = (OAuth2Authentication,)
permission_classes = (IsAuthenticated,)
return Response("Hey there...")
- 从 django-oauth-toolkit 得到一个 access_token:
curl -XPOST "http://172.18.0.1:8000/oauth2/token/" \
-d 'grant_type=client_credentials&client_id=MY-CLIENT-ID&client_secret=MY-CLIENT-SECRET'
{"access_token": "Haje1ZTrc7VH4rRkTbJCIkX5u83Tm6", "expires_in": 36000, "token_type": "Bearer", "scope": "read write groups"}
- 尝试在不设置
access_token
的情况下请求视图:
curl -XGET "http://172.18.0.1:8000/api/v1/test/"
{"detail":"Authentication credentials were not provided."}
- 尝试使用
access_token
的新请求:
curl -XGET "http://172.18.0.1:8000/api/v1/test/" \
-H "Authorization: Bearer Haje1ZTrc7VH4rRkTbJCIkX5u83Tm6"
{"detail":"You do not have permission to perform this action."}
我还应该做些什么来启用 access_token 身份验证吗?
注意:我已经在环境中安装了这些库:
Django==2.2.17
djangorestframework==3.12.2
django-oauth-toolkit==1.3.3
注2:忘记说rest_framework
和oauth2_provider
已经添加到INSTALLED_APPS.
重要编辑:
此问题仅在使用“客户端凭据授予”进行身份验证时存在。在下面检查我自己的答案。
尝试在 Django rest 框架中使用 djoser 进行身份验证
最后我发现 OAuth2Authentication
不通过其 client_credential 验证用户(接受 username/password 与 grant_type= 密码对)。所以我写了这个自定义验证器。希望它能帮助其他遇到同样问题的人。
from oauth2_provider.contrib.rest_framework import OAuth2Authentication
from oauth2_provider.models import Application
class OAuth2ClientCredentialAuthentication(OAuth2Authentication):
"""
OAuth2Authentication doesn't allows credentials to belong to an application (client).
This override authenticates server-to-server requests, using client_credential authentication.
"""
def authenticate(self, request):
authentication = super().authenticate(request)
if not authentication is None:
user, access_token = authentication
if self._grant_type_is_client_credentials(access_token):
authentication = access_token.application.user, access_token
return authentication
def _grant_type_is_client_credentials(self, access_token):
return access_token.application.authorization_grant_type == Application.GRANT_CLIENT_CREDENTIALS