"detail": "Authentication credentials were not provided." for general views
Question:
I have created a custom user model and apply Djoser authentication and jwt. But after this when I tried to get request for products views, I get this error:
"detail": "Authentication credentials were not provided."
Here is the screenshot:
Here is the product_views.py:
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from base.serializers import ProductSerializer ,ProductCategorySerializer
from base.models import Product, ProductCatogory, Review
from rest_framework import status
@api_view(['GET'])
def getProducts(request):
query = request.query_params.get('keyword')
if query is None:
query = ''
products = Product.objects.filter(
name__icontains=query)
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['POST'])
@permission_classes([IsAdminUser])
def createCategory(request):
new_category = ProductCatogory.objects.create()
new_category.save()
return Response('new category created successfully')
@api_view(['PUT'])
@permission_classes([IsAdminUser])
def editCategory(request, pk):
data = request.data
category = ProductCatogory.objects.get(id=pk)
category.product_category = data['product_category']
category.save()
serializer = ProductCategorySerializer(category, many=False)
return Response(serializer.data)
@api_view(['DELETE'])
@permission_classes([IsAdminUser])
def deleteCategory(request, pk):
product_Catogory = ProductCatogory.objects.get(id=pk)
product_Catogory.delete()
return Response('Category is deleted successfully')
@api_view(['GET'])
def getCategorys(request):
product_category = ProductCatogory.objects.all()
serializer = ProductCategorySerializer(product_category, many=True)
return Response(serializer.data)
@api_view(['GET'])
def productsByCategory(request,pk):
category = ProductCatogory.objects.get(id=pk)
products = category.product_set.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['PUT'])
def updateProductCategory(request,pk):
data = request.data
product_id = data['product_id']
product = Product.objects.get(_id=product_id)
category = ProductCatogory.objects.get(id=pk)
product.category = category
product.save()
return Response('category added successfully')
@api_view(['GET'])
def getTopProducts(request):
products = Product.objects.filter(
rating__gte=4).order_by('-rating')[0:5]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['GET'])
def getProduct(request, pk):
product = Product.objects.get(_id=pk)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['POST'])
@permission_classes([IsAdminUser])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name='Sample Name',
price=0,
brand='Sample Brand',
countInStock=0,
description=''
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['DELETE'])
@permission_classes([IsAdminUser])
def deleteProduct(request, pk):
product = Product.objects.get(_id=pk)
product.delete()
return Response('Product is deleted successfully')
@api_view(['PUT'])
@permission_classes([IsAdminUser])
def updateProduct(request, pk):
data = request.data
product = Product.objects.get(_id=pk)
product.name = data['name']
product.price = data['price']
product.brand = data['brand']
product.countInStock = data['countInStock']
product.description = data['description']
product.save()
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['POST'])
def uploadImage(request):
data = request.data
product_id = data['product_id']
product = Product.objects.get(_id=product_id)
product.image = request.FILES.get('image')
product.save()
return Response('Image was uploaded')
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createProductReview(request, pk):
user = request.user
product = Product.objects.get(_id=pk)
data = request.data
# 1 - Review already exists
alreadyExists = product.review_set.filter(user=user).exists()
if alreadyExists:
content = {'detail': 'Product already reviewed'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
# 2 - No Rating or 0
elif data['rating'] == 0:
content = {'detail': 'Please select a rating'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
# 3 - Create review
else:
review = Review.objects.create(
user=user,
product=product,
name=user.first_name,
rating=data['rating'],
comment=data['comment'],
)
reviews = product.review_set.all()
product.numReviews = len(reviews)
# if review = product and product = category
total = 0
for i in reviews:
total += i.rating
product.rating = total / len(reviews)
product.save()
return Response('Review Added')
why I showed it here because I wanna show that there is need to be authenticated to get products.
here is settings.py:
"""
Django settings for backend project.
Generated by 'django-admin startproject' using Django 3.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from datetime import timedelta
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-jyhhr)v0kyrb+^ifdlio=p3mo&l=$(^an7xb&fow--z^rxd7^r'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt',
'djoser',
'base.apps.BaseConfig',
'accounts.apps.AccountsConfig',
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'backend.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'FOOO'
EMAIL_USE_TLS = True
DJOSER = {
'LOGIN_FIELD': 'email',
'USER_CREATE_PASSWORD_RETYPE': True,
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'SEND_CONFIRMATION_EMAIL': True,
'SET_USERNAME_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'USERNAME_RESET_CONFIRM_URL': 'email/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': 'activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'SERIALIZERS': {
'user_create': 'accounts.serializers.UserCreateSerializer',
'user': 'accounts.serializers.UserCreateSerializer',
'user_delete': 'djoser.serializers.UserDeleteSerializer',
}
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAdminUser','rest_framework.permissions.IsAuthenticated', ),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
...
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
# 'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'AUTH_HEADER_TYPES': ('JWT',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/images/'
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CORS_ALLOW_ALL_ORIGINS = True
MEDIA_ROOT = "static/images"
STATICFILES_DIRS = [
BASE_DIR / "static"
]
AUTH_USER_MODEL = 'accounts.UserAccount'
I have searched but they say to change the REST_FRAMEWORK’s AUTHENTICATION PERMISSIONS which I have done as you can see, but to no avail.
Answers:
Did you add tokens in your headers?. if you have added then the access token must have expired so you can get a new access token from the refresh token
Add token in headers like Bearer token.
To open up the API on non-authenticated users, you need to give it an empty list on authentication_classes
:
from rest_framework.decorators import api_view, authentication_classes, permission_classes
@api_view(['GET'])
@authentication_classes([]) # Add this
@permission_classes([]) # Maybe add this too
def getProducts(request):
query = request.query_params.get('keyword')
if query is None:
query = ''
products = Product.objects.filter(
name__icontains=query)
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
This thread is 1 year old but I was facing the same problem and I cannot have unauthorized access to my backend.
The issue with the configuration / usage is here:
'AUTH_HEADER_TYPES': ('JWT',),
When using this configuration the Authorization header must be set with "JWT" instead of "Bearer". Example:
"Authorization: Bearer <JWT token>"
to
"Authorization: JWT <JWT token>"
Another option is to modify the settings file to the following configuration and use the regular Bearer Authorization header:
'AUTH_HEADER_TYPES': ('Bearer',),
I recommend the latest option as it is the most standard one.
Hope this helps!
I have created a custom user model and apply Djoser authentication and jwt. But after this when I tried to get request for products views, I get this error:
"detail": "Authentication credentials were not provided."
Here is the screenshot:
Here is the product_views.py:
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from base.serializers import ProductSerializer ,ProductCategorySerializer
from base.models import Product, ProductCatogory, Review
from rest_framework import status
@api_view(['GET'])
def getProducts(request):
query = request.query_params.get('keyword')
if query is None:
query = ''
products = Product.objects.filter(
name__icontains=query)
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['POST'])
@permission_classes([IsAdminUser])
def createCategory(request):
new_category = ProductCatogory.objects.create()
new_category.save()
return Response('new category created successfully')
@api_view(['PUT'])
@permission_classes([IsAdminUser])
def editCategory(request, pk):
data = request.data
category = ProductCatogory.objects.get(id=pk)
category.product_category = data['product_category']
category.save()
serializer = ProductCategorySerializer(category, many=False)
return Response(serializer.data)
@api_view(['DELETE'])
@permission_classes([IsAdminUser])
def deleteCategory(request, pk):
product_Catogory = ProductCatogory.objects.get(id=pk)
product_Catogory.delete()
return Response('Category is deleted successfully')
@api_view(['GET'])
def getCategorys(request):
product_category = ProductCatogory.objects.all()
serializer = ProductCategorySerializer(product_category, many=True)
return Response(serializer.data)
@api_view(['GET'])
def productsByCategory(request,pk):
category = ProductCatogory.objects.get(id=pk)
products = category.product_set.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['PUT'])
def updateProductCategory(request,pk):
data = request.data
product_id = data['product_id']
product = Product.objects.get(_id=product_id)
category = ProductCatogory.objects.get(id=pk)
product.category = category
product.save()
return Response('category added successfully')
@api_view(['GET'])
def getTopProducts(request):
products = Product.objects.filter(
rating__gte=4).order_by('-rating')[0:5]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
@api_view(['GET'])
def getProduct(request, pk):
product = Product.objects.get(_id=pk)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['POST'])
@permission_classes([IsAdminUser])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name='Sample Name',
price=0,
brand='Sample Brand',
countInStock=0,
description=''
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['DELETE'])
@permission_classes([IsAdminUser])
def deleteProduct(request, pk):
product = Product.objects.get(_id=pk)
product.delete()
return Response('Product is deleted successfully')
@api_view(['PUT'])
@permission_classes([IsAdminUser])
def updateProduct(request, pk):
data = request.data
product = Product.objects.get(_id=pk)
product.name = data['name']
product.price = data['price']
product.brand = data['brand']
product.countInStock = data['countInStock']
product.description = data['description']
product.save()
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
@api_view(['POST'])
def uploadImage(request):
data = request.data
product_id = data['product_id']
product = Product.objects.get(_id=product_id)
product.image = request.FILES.get('image')
product.save()
return Response('Image was uploaded')
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createProductReview(request, pk):
user = request.user
product = Product.objects.get(_id=pk)
data = request.data
# 1 - Review already exists
alreadyExists = product.review_set.filter(user=user).exists()
if alreadyExists:
content = {'detail': 'Product already reviewed'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
# 2 - No Rating or 0
elif data['rating'] == 0:
content = {'detail': 'Please select a rating'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
# 3 - Create review
else:
review = Review.objects.create(
user=user,
product=product,
name=user.first_name,
rating=data['rating'],
comment=data['comment'],
)
reviews = product.review_set.all()
product.numReviews = len(reviews)
# if review = product and product = category
total = 0
for i in reviews:
total += i.rating
product.rating = total / len(reviews)
product.save()
return Response('Review Added')
why I showed it here because I wanna show that there is need to be authenticated to get products.
here is settings.py:
"""
Django settings for backend project.
Generated by 'django-admin startproject' using Django 3.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from datetime import timedelta
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-jyhhr)v0kyrb+^ifdlio=p3mo&l=$(^an7xb&fow--z^rxd7^r'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt',
'djoser',
'base.apps.BaseConfig',
'accounts.apps.AccountsConfig',
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'backend.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'FOOO'
EMAIL_USE_TLS = True
DJOSER = {
'LOGIN_FIELD': 'email',
'USER_CREATE_PASSWORD_RETYPE': True,
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'SEND_CONFIRMATION_EMAIL': True,
'SET_USERNAME_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'USERNAME_RESET_CONFIRM_URL': 'email/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': 'activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'SERIALIZERS': {
'user_create': 'accounts.serializers.UserCreateSerializer',
'user': 'accounts.serializers.UserCreateSerializer',
'user_delete': 'djoser.serializers.UserDeleteSerializer',
}
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAdminUser','rest_framework.permissions.IsAuthenticated', ),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
...
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
# 'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'AUTH_HEADER_TYPES': ('JWT',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/images/'
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CORS_ALLOW_ALL_ORIGINS = True
MEDIA_ROOT = "static/images"
STATICFILES_DIRS = [
BASE_DIR / "static"
]
AUTH_USER_MODEL = 'accounts.UserAccount'
I have searched but they say to change the REST_FRAMEWORK’s AUTHENTICATION PERMISSIONS which I have done as you can see, but to no avail.
Did you add tokens in your headers?. if you have added then the access token must have expired so you can get a new access token from the refresh token
Add token in headers like Bearer token.
To open up the API on non-authenticated users, you need to give it an empty list on authentication_classes
:
from rest_framework.decorators import api_view, authentication_classes, permission_classes
@api_view(['GET'])
@authentication_classes([]) # Add this
@permission_classes([]) # Maybe add this too
def getProducts(request):
query = request.query_params.get('keyword')
if query is None:
query = ''
products = Product.objects.filter(
name__icontains=query)
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
This thread is 1 year old but I was facing the same problem and I cannot have unauthorized access to my backend.
The issue with the configuration / usage is here:
'AUTH_HEADER_TYPES': ('JWT',),
When using this configuration the Authorization header must be set with "JWT" instead of "Bearer". Example:
"Authorization: Bearer <JWT token>"
to
"Authorization: JWT <JWT token>"
Another option is to modify the settings file to the following configuration and use the regular Bearer Authorization header:
'AUTH_HEADER_TYPES': ('Bearer',),
I recommend the latest option as it is the most standard one.
Hope this helps!