1

I am using the DjangoRestFrameworkAPIKey for my Django Project

I have a view to create a client(ClientCreateAPIView), which is only accessible when an API Key is sent. I first create an Organization and then I create an API Key. Then, I try to make a POST request to the ClientCreateAPIView.

I am using POSTMAN to send POST requests. So in Postman, in the "Header" section, I have X-Api-Key written in the Key Field and the API Key in in Value Field. However, whenever I make a POST request, I get a "Authentication credentials were not provided." 403 error. This error does not happen, when I comment out the permission classes code from the view - I can access the view then.

I tried a lot of variations of X-Api-Key, capitalizing them, removing the dashes but nothing seems to work. Also, I know that the API Key exists because in the Django shell, I can print out the id of the APIKey that I am using. I cannot debug what is causing the error.

Following are some code snippets that could be useful:

mysite/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api',
    'rest_framework',
    'rest_framework_api_key',
]

API_KEY_CUSTOM_HEADER = "HTTP_X_API_KEY"

api/models.py

from django.db import models
from rest_framework_api_key.models import AbstractAPIKey

class Organization(models.Model):
    name = models.CharField(max_length=128)

class Client(models.Model):
    name = models.CharField(max_length=128)


class OrganizationAPIKey(AbstractAPIKey):
    organization = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name="api_keys",
    )

api/serializers.py

from rest_framework import serializers
from api.models import Organization, OrganizationAPIKey, Client

class OrganizationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Organization
        fields = ['name',]

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = ['name',]

class OrganizationAPIKeySerializer(serializers.ModelSerializer):

    class Meta:
        model = OrganizationAPIKey
        fields = ('id', 'prefix', 'hashed_key', 'created', 'name', 'revoked', 'expiry_date')

api/views.py

from django.shortcuts import render
from rest_framework import generics
from api.models import Organization, OrganizationAPIKey, Client
from rest_framework import status
from api.serializers import OrganizationSerializer, OrganizationAPIKeySerializer, ClientSerializer
from rest_framework.response import Response
from rest_framework_api_key.permissions import HasAPIKey

class OrganizationCreateAPIView(generics.CreateAPIView):
    """View to create Organziation"""
    serializer_class = OrganizationSerializer

class OrganizationAPIKeyCreateAPIView(generics.CreateAPIView):
    """ View to create API Keys """
    queryset = OrganizationAPIKey.objects.all()
    serializer_class = OrganizationAPIKeySerializer

    def create(self, request):
        orgz = Organization.objects.get(name=request.data['organization'])
        api_key, key = OrganizationAPIKey.objects.create_key(organization=orgz, name=request.data['name'])
        return Response({'name':str(api_key), 'key': str(key)}, status=status.HTTP_201_CREATED)

class ClientCreateAPIView(generics.CreateAPIView):
    """View to create Client"""
    permission_classes = [HasAPIKey]
    serializer_class = ClientSerializer

mysite/urls.py

from django.contrib import admin
from django.urls import path
from api.views import OrganizationAPIKeyCreateAPIView, OrganizationCreateAPIView, ClientCreateAPIView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/organization/', OrganizationCreateAPIView.as_view(), name='organization'),
    path('api/key/', OrganizationAPIKeyCreateAPIView.as_view(), name='key'),
    path('api/client/', ClientCreateAPIView.as_view(), name='client'),
]

0 Answers0