Clean up token-based authentication for GraphQL

This commit is contained in:
jeremystretch 2021-06-28 16:19:02 -04:00
parent 14e27363e0
commit bd1e019a42
2 changed files with 29 additions and 13 deletions

View File

@ -1,20 +1,36 @@
from django.conf import settings
from django.contrib.auth.views import redirect_to_login
from django.http import HttpResponseForbidden
from django.urls import reverse
from graphene_django.views import GraphQLView as GraphQLView_ from graphene_django.views import GraphQLView as GraphQLView_
from rest_framework.decorators import authentication_classes, permission_classes, api_view from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import IsAuthenticated
from rest_framework.settings import api_settings from netbox.api.authentication import TokenAuthentication
class GraphQLView(GraphQLView_): class GraphQLView(GraphQLView_):
""" """
Extends grpahene_django's GraphQLView to support DRF's token-based authentication. Extends graphene_django's GraphQLView to support DRF's token-based authentication.
""" """
@classmethod def dispatch(self, request, *args, **kwargs):
def as_view(cls, *args, **kwargs):
view = super(GraphQLView, cls).as_view(*args, **kwargs)
# Apply DRF permission and authentication classes # Attempt to authenticate the user using a DRF token, if provided
view = permission_classes((IsAuthenticated,))(view) if not request.user.is_authenticated:
view = authentication_classes(api_settings.DEFAULT_AUTHENTICATION_CLASSES)(view) authenticator = TokenAuthentication()
view = api_view(['GET', 'POST'])(view) try:
auth_info = authenticator.authenticate(request)
if auth_info is not None:
request.user = auth_info[0] # User object
except AuthenticationFailed as exc:
return HttpResponseForbidden(exc.detail)
return view # Enforce LOGIN_REQUIRED
if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
# If this is a human user, send a redirect to the login page
if self.request_wants_html(request):
return redirect_to_login(reverse('graphql'))
return HttpResponseForbidden("No credentials provided.")
return super().dispatch(request, *args, **kwargs)

View File

@ -24,4 +24,4 @@ class GraphQLTestCase(TestCase):
self.client.logout() self.client.logout()
response = self.client.get(url, **header) response = self.client.get(url, **header)
with disable_warnings('django.request'): with disable_warnings('django.request'):
self.assertHttpStatus(response, 302) self.assertHttpStatus(response, 302) # Redirect to login page