I have this custom user model:
class CustomUser(AbstractBaseUser,PermissionsMixin):
email = models.CharField(max_length=255, unique=True)
....
And this view that is supossed to require authentication in order to run:
#authentication_classes((TokenAuthentication,))
#permission_classes((IsAuthenticated,))
def test_view(request):
return HttpResponse("Allowed")
When i launch the url for this, it will always run no matter if i provide credentials or not in my authorization header. My guess is that rest framework is using django's default user model, since the request.user object contains an AnonymousUser instance. But i have checked the database, and the authtoken table is referencing my custom user table.
I thoguht that this should be as simple as my code is, but i guess im missing something. Any ideas?
Edit: here are more details:
settings.py:
INSTALLED_APPS = (
'myapps',
...
'django.contrib.auth', #should this be enabled?
...
'rest_framework.authtoken'
)
...
#I think this is unnecesary since i use per-view decorators, but...
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
AUTH_USER_MODEL = 'users.CustomUser'
urls.py:
urlpatterns = patterns('',
...
url(r'^test', test_view, name='test'),
...
)
just add #api_view(['GET']) decorator to your view like
from rest_framework.decorators import api_view
#api_view(['GET'])
#authentication_classes((TokenAuthentication,))
#permission_classes((IsAuthenticated,))
def test_view(request):
return HttpResponse("Allowed")
Add the following to settings.py
If you're using DRF token Auth:
INSTALLED_APPS = (
...
'rest_framework.authtoken'
)
If you're using JWT Auth:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
...
}
Related
I have my token for admin, the booking entries is allowed in Insomnia but would not be allowed DRF display. I am missing something please? Is there way to provide the token for it to be allowed?
#view.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from rest_framework import viewsets
from .models import Booking, Menu
from .serializers import BookingSerializer, MenuSerializer, UserSerializer
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework import generics
from datetime import datetime
from django.views.decorators.csrf import csrf_exempt
from django.db.models import Sum
from django.contrib import messages
def home(request):
return render(request, 'index.html')
def about(request):
return render(request, 'about.html')
class UserRegistrationView(generics.CreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class BookingViewSet(viewsets.ModelViewSet):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
permission_classes = [IsAuthenticated]
authentication_classes = [TokenAuthentication]
settings.py
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
'DEFAULT_AUTHENTICATION_CLASS': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
Select Headers Key will be Authorization and value will be like this
Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
I think you need to remove session authentication class because here you used token for authentication
I mean authentication classes overrides.
So, remove session authentication class only put token authentication class
But, you want to authenticate with browsable you need to remove token authentication and need to put session authentication class.
If you want authenticate with with token you need to POSTMAN or other third -party API testing tool which support token authentication
and you need to remove session authentication and need to put token authentication class
settings for token authentication (test with Postman or other third -party API testing tool)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
'DEFAULT_AUTHENTICATION_CLASS': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
settings for session authentication (test with browsable api which provides DRF built-in)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
'DEFAULT_AUTHENTICATION_CLASS': (
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
how to change permissions for current view overriding the DEFAULT_PERMISSION_CLASSES in django rest-framework
Here is how i set my defaultpermissions in my settings.py :
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
and i need to use AllowAny on the signUp method :
#permission_classes([AllowAny,])
#api_view(["POST", ])
def add_new_user(request):
if request.method == "POST":
lang = request.data["lang"]
..........
.........
.......
Still, it returns Authentication credentials were not provided. .. I mainly need to have permissions with a token with every request but not the register and login request. how to do it ??
A Way to do that is using Object Level Permissions in Django.
You just setup as normally in settings.py and add manually a permission into every class view.
For me is the best way to do it. Normally will be Views witch is are Admin only, Authenticated or just Open.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoObjectPermissions',#Object Level Permission
]
}
After set this line into your settings.py just follow adding a permission_classes into view. Like:
class LoginUser(APIView):
permission_classes = [AllowAny, ]
...
References
DjangoObjectPermissions
Django Class Based Views
Here is how I solved this :
in my settings.py i added both permissions classes
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', #both are mentioned
'rest_framework.permissions.AllowAny',
]
}
and in my view, I had to move the permission dictator to be the last thing before the view itself.
#api_view(["POST", ])
#permission_classes([AllowAny])
def login_user(request):
if request.method == "POST":
lang = request.data["lang"]
...
I want to create global authentication with middleware django restframework which check every request user authenticate or not.
I don't want to add code on every view class like this
#permission_classes([IsAuthenticated])
class UserProfile(APIView):
You just need to set the permissions policy for DRF in your settings.py file. Here the Docs
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
So the problem I have already mentioned. I am a beginner, I might be doing some silly mistakes. So humble request to you guys to address my mistake and help me to complete my project. Thanks you all in advance.
setting.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600),
}
this is the setting.py file and here I mention the required file
view.py
class LoginViewSet(viewsets.ViewSet):
""" Check email and password and return auth token. """
serializer_class = AuthTokenSerializer
authentication_classes((SessionAuthentication, TokenAuthentication, BasicAuthentication))
permission_classes((IsAuthenticated,))
def create(self, request):
""" Use ObtainAuthToken APIView to validate and create a token. """
return ObtainAuthToken().post(request)
this is the view.py file.
urls.py
router.register('login', views.LoginViewSet, base_name="login")
urlpatterns = [
path('', include(router.urls)),
path('login/', ObtainAuthToken.as_view()),
path(r'api-token-auth/', obtain_jwt_token),
path(r'api-token-refresh/', refresh_jwt_token),
]
Error Message
error
you must define http_method_names in DRF and specify your method access in your api.
class IndexViewAPI(generics.GenericAPIView):
http_method_names = ['get', 'head']
# some statements
I have integrated django-rest-framework with django-oauth-toolkit. And it is giving me {"detail": "Authentication credentials were not provided."} with un authenticated apis.
Here's my settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class SignUpView(APIView):
"""
Signup for the user.
"""
def get(self, request):
return Response({'result': True, 'message': 'User registered successfully.'})
urls.py
from django.urls import path
from myapp.views import SignUpView
urlpatterns = [
path('signup/', SignUpView.as_view()),
]
For registering a user, you do not need any authentication. So you need to write your view like this.
class SignUpView(APIView):
"""
Signup for the user.
"""
authentication_classes = ()
permission_classes = ()
def get(self, request):
return Response({'result': True, 'message': 'User registered successfully.'})
For all other requests, you need to pass auth token in your header. In that case, you will not have any need to mention authentication and permission classes as your default classes will be used.