I'm trying to add an API using the Django REST framework to an existing codebase which uses the Django OAuth2 toolkit. The existing views make use of the fact that the OAuth2 toolkit's backend modifies the behavior of Django's login_required
decorator so that it uses OAuth2 authentication. The function-based views look similar to the one in the tutorial example:
from django.contrib.auth.decorators import login_required
from django.http.response import HttpResponse
@login_required()
def secret_page(request, *args, **kwargs):
return HttpResponse('Secret contents!', status=200)
I'm trying to adapt the example given on https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html to my situation, but I'm finding it's not an exact correspondence, because the example uses the DRF's ModelViewSet
classes whereas my current view uses a (less-integrated) generic class-based view:
from rest_framework import generics
from ..models import Session
from ..serializers import SessionSerializer
class SessionDetail(generics.UpdateAPIView):
queryset = Session.objects.all()
serializer_class = SessionSerializer
where I've set the default permission class to IsAuthenticated
in settings.py
:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
This should allow a Session
object to be updated using PATCH requests, but it appears to return a 403 Forbidden
response for use cases similar to the ones for the current views decorated with login_required
.
How can I update the SessionDetail
view so that it behaves the same as a function view decorated with login_required
? I suspect that I need to use the TokenHasReadWriteScope permission class, since this appears to be the only one for which the required_scopes
is optional. (The views decorated with login_required
don't provide required_scopes
either).
Would it be like this:
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from oauth2_provider.contrib.rest_framework import OAuth2Authentication, TokenHasReadWriteScope
from ..models import Session
from ..serializers import SessionSerializer
class SessionDetail(generics.UpdateAPIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasReadWriteScope]
queryset = Session.objects.all()
serializer_class = SessionSerializer
Also, would I have to update my REST_FRAMEWORK
setting with a DEFAULT_AUTHENTICATION_CLASSES
like this:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
)
}
Right now if I run the server and try to make a patch request with the browsable API, I get a 401 Unauthorized
error:
Also if I Log in
using a username and password that I just created using python manage.py createsuperuser
, it goes straight back to this 401
page instead of one with a form to make a PATCH request as I'd expect.
Any ideas on how to fix this?