Django Rest Framework JWT "Authentication credentials were not provided."} - python

I am trying to write a simple API that uses JWT tokens to authenticate.
My settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
'rest_framework.permissions.IsAdminUser'
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
'PAGE_SIZE': 10
}
And my View looks like this:
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
authentication_classes = (JSONWebTokenAuthentication,)
def get(self, request, format=None):
return JsonResponse({"username":str(request.user)})
Which really does nothing, but I don't even get there. I have registered the JWT Token provider as in the documentation with url(r'^api-token-auth/', obtain_jwt_token) and I receive a token when I call this endpoint.
However, when I then make a request against my APIView (which contains the header Authorization: JWT <my_token> I always receive the following error:
[Response]: 403 [Data]: {"detail":"Authentication credentials were not provided."}
What am I missing? Thanks in advance!

If you are using apache as web server then add the following in apache httpd.conf file:
WSGIPassAuthorization On
This worked for me.

Related

DRF Token Authentication - not able to retrieve Token on Postman

I'm trying to retrieve a token for the user using the following request through Postman.
http://127.0.0.1:8000/api-token-auth/
JSON Body -
{
"username": "user1",
"password": "testpass"
}
The following is the error response -
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
I've checked the instructions provided in the official DRF Authentication document as well as various other question posts and implemented the following code.
settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_auth',
'rest_auth.registration',
....
]
AUTH_USER_MODEL = 'users.CustomUser'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
signals.py
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
urls.py
from django.contrib import admin
from django.urls import include, path, re_path
from django_registration.backends.one_step.views import RegistrationView
from rest_framework.authtoken import views as authtoken_views
urlpatterns= [
path('admin/', admin.site.urls),
path("accounts/",
include("django_registration.backends.one_step.urls")),
path("accounts/",
include("django.contrib.auth.urls")),
path("api-auth/",
include("rest_framework.urls")),
path("api-token-auth/", authtoken_views.obtain_auth_token, name="api-token-auth"),
path("api/rest-auth/",
include("rest_auth.urls")),
path("api/rest-auth/registration/",
include("rest_auth.registration.urls")),
]
Have I missed something?
Found the issue.
The issue was not with the implementation, rather it was with Postman. Postman interceptor had retrieved cookies from the browser and had stored the CSRF Token with it. This token was automatically added to the request headers and hence, django tried to authenticate this request from Session Authentication which naturally should fail.
The solution-
Open the Postman cookies and Delete the CSRF Token.
PS- A curl request can always help in verifying such issues

Can Django Tenant Schema work with Django Rest Framework?

I am creating a SaaS app with Django, Django Tenant Schema and Django Rest Framework. Everything works fine without an API but I have issues with sending a get request to different Tenants via an API call. It returns users from all the tenants in the database even if I specify the subdomain.
However, a get request to a none API endpoint works fine, in fact, everything done outside the API endpoint works great.
For Example:
http://goldlimited.localhost:8000/dashboard/api/users
Returns the same information as
http://missinglinkgm.localhost:8000/dashboard/api/users
The view is a basic ModelViewSet
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.filter()
serializer_class = UserSerializer
And the Serializer
class UserSerializer(ModelSerializer):
class Meta:
model = User
exclude = ("password",)
And Route
router = routers.DefaultRouter()
router.register('user', UserViewSet, 'user')
I am wondering if there is a configuration I am missing to make DRF work with Django Tenant Schema.
Yes it does work, little bit of tweaking to settings.py would work. Make sure you add rest_framework to INSTALLED, TENANT APPS.
SHARED_APPS = [
'tenant_schemas',
'Client',
'django.contrib.contenttypes',
# include below if you need admin panel on main site(public schema)
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
# include other apps here
# 'rest_framework' # if needed or if you're handling auth
]
TENANT_APPS = [
'django.contrib.contenttypes',
# include below if you need admin panel on every tenant
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
# include other apps here
'rest_framework', # mandatory
]

Token Authentication Not Working on Django Rest Framework

I have a Django application, which I am using DRF for my API with Session, and Token authentication. I have rest_framework, and rest_framework.authtoken in my installed apps. I have migrated my database and can create tokens for users in the Django Admin. I know all of this is working because I am accessing rest_framework.auth_token's obtain_auth_token view for returning a token when user data is submitted in a POST request, and receive one back. When I try to make a GET request to a view function in my app that has TokenAuthentication on its viewset, it keeps returning.
{"detail":"Authentication credentials were not provided."}
Settings File
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# My Apps
'rest_framework',
'rest_auth',
'rest_framework.authtoken',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
}
URLS
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework.authtoken import views
from api.views.some_model import MyViewSet
urlpatterns = [
path('', include(router.urls)),
path('rest-auth/', include('rest_auth.urls')),
path('api-token-auth/', views.obtain_auth_token)
]
Viewset
from rest_framework.viewsets import ModelViewSet
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from some_app.models import SomeModel
from api.serializers.exams import SomeModelSerializer
class ExamViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,)
authentication_classes = (TokenAuthentication, SessionAuthentication)
queryset = SomeModel.objects.all()
serializer_class = SomeModelSerializer
Python Script to Get Response
import requests
import json
data = {
"username": "myemail#gmail.com",
"password": "password124"
}
url = "http://localhost:8002/api/v1/api-token-auth/"
response = requests.post(url, data=data)
token = json.loads(response.text).get('token')
if token:
token = f"Token {token}"
headers = {"Authentication": token}
response = requests.get("http://localhost:8002/api/v1/model/", headers=headers)
print(response.text)
else:
print('No Key')
Header name should be Authorization not Authentication:
headers = {"Authorization": token}
response = requests.get("http://localhost:8002/api/v1/model/", headers=headers)
The token should be provided in the header like
-H "Authorization: Token 8fa36c01df3bb9ed31fc2329c53a9fe2cac72966"
Authorization:prefix YourToken
If you are using JWT authentication then your request header should look like
Authorization: JWT your-token-here
or
Authorization: Bearer your-token-here

Django how to use login_required with TokenAuthentication

Hi I am trying to use TokenAuthentication from Django rest-framework.
I am able to use this with my views with rest api.
#view_rest.py
class CartList(generics.ListCreateAPIView):
serializer_class = CartSerializer
filter_class = CartFilter
permission_classes = (permissions.IsAuthenticated,)
def create(self, request, *args, **kwargs):
request.data['user_id'] = request.user.id
return generics.ListCreateAPIView.create(self, request, *args, **kwargs)
def get_queryset(self):
user = self.request.user.id
return Cart.objects.filter(user_id_id=user)
But In my custom views it is not authenticating,
#custom_django_views.py
#login_required(login_url='/login/')
def order(request):
'''Returns page to place order
'''
return render(request,"order.html",{})
#this will redirect me to login page.
#settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'myapp',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'site_aggrigator.middleware.SubdomainMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
#rest framework
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'rest_framework.filters.DjangoFilterBackend',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
'rest_framework.permissions.DjangoObjectPermissions',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
I am not able to understand why request for custom_django_views, is not authenticated? When does authentication happens?
The use case is wrong. Django rest framework doesn't allow these things.
http://www.django-rest-framework.org/topics/ajax-csrf-cors/#javascript-clients
Session authentication should be used for web browser. And they are not required when using it for mobile.
Rest framswork views take care of csrf validation when using token authentication.
This worked for me.
from rest_framework.decorators import api_view
#api_view(["GET"])
def your_function(request):
pass

Django allauth session JSON serializable error after login

I have installed django-allauth, after that this is my settings.py
Django_apps = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
)
Third_party_apps = (
'avatar',
'allauth',
'allauth.account',
'allauth.socialaccount',
'bootstrapform',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.twitter',
)
My_apps = ()
INSTALLED_APPS = Django_apps + Third_party_apps + My_apps
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
"django.core.context_processors.request",
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount",
)
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
)
ACCOUNT_ADAPTER ="allauth.account.adapter.DefaultAccountAdapter"
ACCOUNT_AUTHENTICATION_METHOD = "username_email"
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = "optional"
ACCOUNT_USERNAME_MIN_LENGTH = 3
and i believe i also correctly set my urls.py. And also i have two Social app from django admin with correct twitter and github api keys and secrets.
But then problem is whenever i click to login via twitter it shows me the correct twitter auth page and after i authorize the app it gives me this error..
<allauth.socialaccount.models.SocialLogin object at 0x7feb5875a650> is not JSON serializable
and also i get almost the same error with github. like
<allauth.socialaccount.models.SocialLogin object at 0x7feb5877a590> is not JSON serializable
, So please help me to understand what's the problem
In Django 1.6 you have to change the SESSION_SERIALIZER parameter to pickle. Put this in your settings.py:
SESSION_SERIALIZER='django.contrib.sessions.serializers.PickleSerializer'
I don't know when allauth will become compatible with this new Django serialization format. See Django 1.6 release notes.

Categories

Resources