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'),
]