DRF APIview with authentication - django

I have a class someAPI(APIView). I would like this one to be accessed by only authorised users.
I tried this link How to use login_required in django rest view
and
https://www.django-rest-framework.org/api-guide/authentication/
but none of them seem work.
My current authentication protocol is logging in with username and password. I guess a reason is because I implement this authentication with basic django (https://docs.djangoproject.com/en/3.1/topics/auth/default/) but not DRF.
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from django.http import JsonResponse
class APICostAnalysisController(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
""" Initiate get API for getting cost analysis """
return JsonResponse(APICostAnalysisImpl().get(), safe=False,json_dumps_params={'indent': 2})

Related

How to use GraphQL customized Authentication class?

With Django REST Framework(DRF) I can customize Authentication class and Permission class simply like this
from django_cognito_jwt import JSONWebTokenAuthentication
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
class CognitoQuestionViewSet(viewsets.ModelViewSet):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
queryset = Question.objects.all()
serializer_class = QuestionSerializer
In the GraphQL docs. It is using standard Django login which is different from my project. I had checked with source LoginRequiredMixin but no luck. I don't see Authentication class there then I can override it
Problem:
How to customize GraphQL Authentication class and Permission class like one I did in DRF
After trials and tries with django-graphql-jwt with no luck. vinayan3 has the answer on my question. Because django-cognito-jwt is considered as a DRF complement.
Solution:
Just replace TokenAuthentication with JSONWebTokenAuthentication from django_cognito_jwt

Allow both authenticated and unauthenticated users access a django rest view with token authentication decorator

I am working with django rest, I however have an issue in one of my views because, i want to allow both authenticated users and unauthenticated users access the view then check if the user is authenticated then there are some special events to be done by the celery tasks, however, whenever i add the decorator for the authentication_classes, unauthenticated users can no longer visit the page even after setting the permission_classes to allow all
simply my code is here, hope someone can know what i need to add or remove
#api_view(['GET'])
#permission_classes([AllowAny])
#authentication_classes([TokenAuthentication])
def item_details(request, pk):
if request.user.is_authenticated:
#here some tasks
the main issue is that it seams that TokenAuthentication just nullify AllowAny and takes over the checking of the permisssion class
or is there something am doing wrong?
Overriding the authenticate method of TokenAuthentication
myauth.py
from rest_framework.authentication import TokenAuthentication
class TokenAuthenticationSafe(TokenAuthentication):
def authenticate(self, request):
try:
return super().authenticate(request=request)
except:
return None
views.py
from myauth import TokenAuthenticationSafe
#api_view(['GET'])
#permission_classes([AllowAny])
#authentication_classes([TokenAuthenticationSafe])
def item_details(request, pk):
if request.user.is_authenticated:
#here some tasks

Django Rest Framework User and UserRole and Permission Handling using Token Authentication

I am newbie to Django Rest Framework. I googled a lot and stuck on How to set User Role to User and strict to Permission.
My question is very basic but I don't know how to do it.
I want to create 2 types of Users:
1) Admin (Full Access)
2) Normal User (Limited Access)
I found some links but still on getting what to do:
Django rest-framework per action permission
django-rest-framework : setting per user permissions
you can separate users by is_staff property and use, standart rest permission isadminuser, for test you try this simple view
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAdminUser,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)

Django REST Framework - Custom Permissions not Evaluating

I'm trying to set custom permissions on a class that extends viewsets.ModelViewSet and it appears that my permissions are not being evaluated. Here is my view:
from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
import models
import serializers
from permissions import IsAdminOrAuthenticatedReadOnly
class KPIViewSet(viewsets.ModelViewSet):
'''
API endpoint that allows KPI metadata to be viewed or edited
'''
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAdminOrAuthenticatedReadOnly,)
queryset = models.KPI.objects.all()
serializer_class = serializers.KPISerializer
And here is my permission class:
from rest_framework.permissions import BasePermission, SAFE_METHODS
class IsAdminOrAuthenticatedReadOnly(BasePermission):
def has_permissions(self, request, view):
if request.method in SAFE_METHODS:
return request.user and request.user.is_authenticated()
return request.user and request.user.is_staff()
The problem I'm running into is that IsAdminOrAuthenticatedReadOnly never seems to get evaluated. I tested this both by forcing it to always return "False" and by switching the permission_classes value to "IsAuthenticated" in the view. In the former scenario, a request to the endpoint returns as if there were no authentication requirement. In the later, authentication is enforced as expected.
Any ideas what I'm missing?
The method name is has_permission not has_permissions (no s) ;)

Django, TastyPie, Authentication, and custom middleware headache

I have a Django web application which requires authentication across the whole site. I've accomplished that with custom middleware which basically test if request.user.is_anonymous and, if they are, redirects them to the login page. It looks like this:
from django.contrib.auth.views import login
from django.contrib.auth import authenticate
from django.http import HttpResponseRedirect, HttpResponse
from django.utils import simplejson
from django.core import serializers
class SiteLogin:
"This middleware requires a login for every view"
def process_request(self, request):
if request.path != '/accounts/login/' and request.user.is_anonymous():
if request.POST:
return login(request)
else:
return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)
Now I'm making an iOS app which, for now, will just do GET requests off the Django server. I am trying to use TastyPie to do this but I can't get the the authentication working. I am using ApiKeyAuthentication and, I believe, have set it up properly. However, it just redirects me to the login page. I'm wondering if I need to edit this middleware to handle TastyPie requests, but I thought TastyPie could to auth for me...
I feel like my situation is very similar to this question, but I wonder if my custom middleware is getting in the way.
Here's my api.py:
from django.contrib.auth.models import User
from django.db import models
from tastypie.resources import ModelResource
from cpm.systems.models import System
from cpm.products.models import Product
from tastypie.models import create_api_key
from tastypie.authentication import ApiKeyAuthentication
from tastypie.authorization import DjangoAuthorization, Authorization
models.signals.post_save.connect(create_api_key, sender=User)
class SystemResource(ModelResource):
class Meta:
queryset = System.objects.all()
resource_name = 'system'
authentication = ApiKeyAuthentication()
authorization = DjangoAuthorization()
class ProductResource(ModelResource):
class Meta:
queryset = Product.objects.all()
resource_name = 'product'
authentication = ApiKeyAuthentication()
authorization = DjangoAuthorization()
And a portion of my urls.py:
from cpm.ios.api import SystemResource, ProductResource
from tastypie.api import Api
v1_api = Api(api_name='v1')
v1_api.register(SystemResource())
v1_api.register(ProductResource())
admin.autodiscover()
urlpatterns = patterns('',
# iOS TastyPie related:
(r'^ios/', include(v1_api.urls)),
# .... more urls....
The URL I try to navigate to is:
http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345?format=json
But I'm just redirected to my login page. I've followed the tutorial to a tee, created an api key on my Admin panel, and added WSGIPassAuthorization On to my apache config.
Any ideas?
EDIT I just removed that middleware altogether and now all I receive are 401 AUTHENTICATION errors...
EDIT 2
I should point out that if I remove the ?format=json then I get a response of: Sorry, not implemented yet. Please append "?format=json" to your URL.. So it's like it does authenticate, but then fails because I'm not specifying the format.
So my URL looks like this: http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345 but as soon as I add the ?format=JSON then it goes to a 401 error.
TastyPie requests go through the same stack of middlewares as any typical django request. So, it's definitely your middleware. You have to rethink it, or just drop to the basics and use #login_required.
The api key doesn't work after you disabled the middleware because your URL is malformed. You can't use a ? in a querystring after you used it once. Try this url:
http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345&format=JSON