How to deal with authorization with DRF and React - django

I'm building an app using Django as backend and React as frontend, for the user authentication I will use JWT Authentication. My doubt is when I need to get data from the API without the need to be an authenticated user, how I accomplish this? Using API keys?. I read that API keys are not mean for Authentication but authorization? This will be the case?

You can set authentication_classes = [] in your class for no authentication. If you want permission classes the you can use permission_classes
Example:
class SnippetDetail(CreateAPIView):
authentication_classes = [BasicAuthentication]
permission_classes = []
Reference: https://learnbatta.com/blog/permissions-in-django-rest-framework-82/

Related

I have configured Django REST Framework API Key, I want to expose one API to call without API key in Authorization header, What configuration needed?

This is the code block I have added to my settings.py file. Is there any way to expose an API that can be called without an authorization header?
I don't want to use the JWT token. There is no user interface in the application its an integrator project.
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework_api_key.permissions.HasAPIKey",
]
}
If you use AllowAny permission, then you will not need any authorization, authorization header and token etc. API will be public/open to all.
Add AllowAny in the permission_classes attribute of the view.
from rest_framework import permissions
class ExampleView(generics.RetrieveAPIView):
permission_classes = [permissions.AllowAny]
Note:
It does not have to be a generics.***APIView. It works with APIView too. Also for the function-based views, you can use decorators.
#api_view(['GET'])
#permission_classes([permissions.AllowAny])
def example_view(request, format=None):
...
Reference: https://www.django-rest-framework.org/api-guide/permissions/#allowany

getting the current user with Django drf and simple jwt

I was trying to get the current user with rest framework and simple jwt
I'm new to Django and I wrote a simple view that does(ish) the job
class UserDetail(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
authentication_classes = [JWTAuthentication,]
permission_classes = [IsAuthenticated,]
but for some reason when I post the user credentials to the endpoint in postman it says
{
"detail": "Authentication credentials were not provided."
}
but when I remove the ==> authentication_classes = [JWTAuthentication,] and
permission_classes = [IsAuthenticated,]
it works and gite the current user, my question is is this the right way of doing it, and are there any risks in doing it this way and if their is a better and more secure way of doing it. thanks in advance!!
this is the screenshot of the postM request data
and this is the URL for the class:-
path('detail/', UserDetail.as_view({'get':'list'}), name="blacklist"),
You have to pass the access token in the request.
If you are not confident in setting up simplejwt, follow this guide:
If you use postman to test the API, you can provide Authorization details like shown in this image
If you are using any other medium to send requests, then you can add Authorization in the request's header: {"Authorization": "Bearer <access_token>"}
if you are able to generate the token. All you have to do is pass the token in Postman url localhost:8000/detail/ and under the Authorization tab, select the Bearer token and paste the token which has been generated and send it. Under settings.py edit Simple JWT settings by adding Bearer after JWT in AUTH_HEADER_TYPES. Hope this works for you.

Django Rest Framework resource doesn't respond to request with invalid token

I have Django project with ViewSet model inherited from Django Rest Framework models.GenericViewSet
At the top of the ViewSet I've set up authentication with
permission_classes = (permissions.IsAuthenticated,)
When I make a request with an existing token, it works as expected. But if the token doesn't exist, the server seems to never respond.
How can I debug this behavior? Or probably do I need something else for this permission class to properly process invalid tokens?
I need the server to respond with something about wrong credentials. For example, 401 and some custom message (if there is no better alternative).
Have you tried to put this code inside your view?
authentication_classes = (SessionAuthentication, BasicAuthentication, TokenAuthentication)

User Authentication in Django REST Framework

I have a Django REST backend, and it has a /users endpoint where I can add new users through POST method from frontend.
/users endpoint url:
http://192.168.201.211:8024/users/
In this endpoint I can view all users information and add new user, so I must avoid others entry it except Administrator. I create a superuser admin with password admin123 by python manage.py createsuperuser.
My question is, If I want to do a HTTP POST from frontend(I use Angular) I have to pass the Administrator's user name and password, admin and admin123, along with POST head information. So I let others know the user name and password who check the source code of frontend.
Is there any other way to do this Authentication without exposing Administrator's user name and password to others?
You need to create an API that handles the user creation. This is why we create backends. The user will send the API their credentials and the API will add the user to the database using the admin credentials and post request. The API's code will not be viewable. Depending on your needs, auth0 can be a good solution and save you time on user registration and login. If you make your own sign up and login be sure to hash passwords and make sure they are sent over SSL. A service like auth0 will handle all this for you if you want to focus on other parts of your project.
token auth is may what you need,i use token auth for DRF as backend and angular as frontend
Finally, I find a method to solve this problem.
Here has a very elegant way to do this, rewrite get_queryset function in my UserViewSet:
class UserViewSet(viewsets.ModelViewSet):
# permission_classes = (permissions.IsAdminUser, )
permission_classes = (permissions.AllowAny, ) # <-- change 1
# queryset = User.objects.all() # <-- change 2
serializer_class = UserSerializer
def get_queryset(self):
queryset = User.objects.filter(id=self.request.user.id)
if self.request.user.is_superuser:
queryset = User.objects.all()
return queryset
In change 1, permissions allowed anyone to access, so a new user can do a POST without any authentication.
In change 2, I only return all users when the user is superuser, just like rewrote get_queryset done.
Also need to change urls.py file to add base_name for this url like this:
router.register(r'users', UserViewSet, base_name='user')
ref, https://stackoverflow.com/a/22767325/2803344

Django Tastypie OAuth 2.0 returning Anonymous user in request.user

I followed this implementation: Building a True OAuth 2.0 API with Django and Tasty Pie to bring OAuth2 Two-legged authentication to my Django app.
It works perfectly and authentication using session keys is terrific, however, I am facing some issues retrieving the user authenticated using OAuth, as request.user always returns an Anonymous user object.
I don't know whether I should include any other method in the api/authentication.py, but right now I'm using this one: https://github.com/amrox/django-tastypie-two-legged-oauth/blob/master/src/authentication.py
I guess that custom authentication is not taking care of returning the current user authenticated at all, but I'm unable to handle it myself.
This is my resource:
class UpdateResource(ModelResource):
class Meta:
resource_name = 'updates'
queryset = Update.objects.all()
allowed_methods = ['get', 'post']
authorization = DjangoAuthorization()
authentication = OAuth20Authentication()
def hydrate(self, bundle, request=None):
print bundle.request.user
Any help would be appreciated,
Thanks.
EDIT: I can retrieve correctly the user in GET requests, but POST request don't seem to go through my custom authentication, so I guess it must have something to do with Django CSRF protection. :(