brno32
brno32

Reputation: 424

Authentication credentials were not provided with Django Rest Framework JWT

I am having trouble implementing token authentication with JWT in the Django rest framework with a Typscript frontend. I'm getting

{detail: "Authentication credentials were not provided."}

with my API call via Typescript, which is:

  readonly BASE_URL = 'http://127.0.0.1:8000/'
  api_url = this.BASE_URL + 'items/'
  auth_url = this.BASE_URL + "api-token-auth/"

  getItemsService(token) {
    const headers = new HttpHeaders()
    headers.append('Content-Type', 'application/json')
    headers.append('Authorization', 'JWT ' + token.token)
    return this.http.get(this.api_url, {headers: headers})
  }

Logging in works fine. It's when I try to load the items that I have issues.

Here's my Django code:

views.py

from rest_framework import generics
from .models import Item
from .serializers import ItemSerializer


class ItemList(generics.ListCreateAPIView):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer


class ItemDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer

items/urls.py

from django.urls import path
from .views import ItemList, ItemDetail

urlpatterns = [
    path('', ItemList.as_view()),
    path('<int:pk>/', ItemDetail.as_view()),
]

project/urls.py

from django.contrib import admin
from django.urls import include, path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('items/', include('groceries.urls')),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('api-token-auth/', obtain_jwt_token),
]

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

I thought the issue would have to be with Django, but I am able to get what I expect with

curl -H "Authorization: JWT <token>" http://localhost:8000/items/

If my backend was not set up correctly, this wouldn't work. So it must be my frontend code.

Upvotes: 1

Views: 1890

Answers (1)

Reza Torkaman Ahmadi
Reza Torkaman Ahmadi

Reputation: 3058

Based on what you described, It may be a CORS issue. Because you have access to your api endpoint via curl command. But not with browser.

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.

I checked your Angular typescript code, It seems fine. I suggest to follow below instructions in your django project and see how it goes:

1) install it for pip via pip install django-cors-headers command.

2) In settings.py file, add this app to your installed apps:

INSTALLED_APPS = (
...
'corsheaders',
...
)

3) You will also need to add a middleware class to listen in on responses:

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]

remember CorsMiddleware should be placed as high as possible.

4) Add this line to your settings.py file.

CORS_ORIGIN_ALLOW_ALL = True

for full documentation refer to django-cors-headers.

Upvotes: 1

Related Questions