getting the current user with Django drf and simple jwt - django

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.

Related

Django Rest Framework not accepting JWT Authentication Token

I am using the Django Restful API Framework together with Simple JWT and have successfully created a URL for receiving and refreshing a user token.
In order to try out the authentication using the token, I have created a view that simply lists all the posts inside the database. I have then assigned the IsAuthenticated class to the view.
As expected, I get an error message saying that the authentication credentials were not provided. I then went ahead and made a simple GET request using Postman, with the authentication token provided in the "Authorization" tab. The type was set to "Bear Token". Unfortunately, I still get the message "Authentication credentials were not provided." with a 403 Forbidden code.
I have also tried to provide the token in the Headers, as well as make CURL requests, everything to no avail.
My view looks like this:
class PostListView(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
queryset = Post.objects.filter()
This is the serializer:
class PostListSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('__all__')
The settings.py of the Django project:
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'],
'DEFAULT_AUTHENTICATION_CLASSES:': ('rest_framework_simplejwt.authentication.JWTAuthentication',)
}
CORS_ALLOW_ALL_ORIGINS = True # For testing purposes
I have followed several different tutorials online, read through numerous posts as well as followed the official documentation of Simple JWT.
Well what you are doing is trying to filter the data while your basic purpose is to just list your model. For filtering make sure your go through the documentation DRF Filtering.
Try these changes in your code. I hope it will work for you.
Settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
Views.py
class UserList(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
queryset = Post.objects.all()
serializer_class = PostListSerializer
After this try to hit your API with access token. To learn more about generic views you can go through this link Generic Views in DRF.

How to deal with authorization with DRF and React

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/

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)

How to get and save token using Django Web service

I'm not sure I'm right on track. Please give me a hint or direction.
I set up my Web service using Django and also made mobile app with React Native using Django REST framwork. Django uses the basic session authentication, but Django REST API uses token authentication to process the request from mobile app.
I want to implement small ReactJS app into my existing Django web. At this stage, I think my small react app will need auth token to communicate with REST api for itself.
So, my idea is that when user logs in web login page, user's API token needs to be received from API and save into cookie or localStorage while normal log in process is processing in Django Web service. Because I don't want to let users log in again to run react app on my web page to get auth token.
Am I right on track? if so, how can I make it works? Please refer to my code in Django login view.py Do i need to some code in order to get API auth token and save it into client side?
def Login(request):
if not request.user.is_authenticated:
if request.method == "POST":
email = request.POST['email']
password = request.POST['password']
user = authenticate(email = email, password = password)
if user is not None:
login(request, user)
messages.add_message(request, messages.SUCCESS, request.user.nickname + ' Welcome!')
return redirect('Search')
else:
messages.add_message(request, messages.WARNING, 'Please check Email / Password again')
return redirect('login')
else:
form = LoginForm()
return render(request, 'login.html', {'form': form })
else:
return redirect('main')
You have done some useless in your login function. you can use jwt. it has some good function for supporting login. In its login function, when send username and password with post, it return token to client.
http://getblimp.github.io/django-rest-framework-jwt/
You just need set urlpattern
from rest_framework_jwt.views import obtain_jwt_token
#...
urlpatterns = [
'',
# ...
url(r'^api-token-auth/', obtain_jwt_token),
]
It return token
$ curl -X POST -d "username=admin&password=password123" http://localhost:8000/api-token-auth/
In other request, if you need authentication, use following request
$ curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/
They both carrying out similar tasks with few differences.
Token
DRF's builtin Token Authentication
One Token for all sessions
No time stamp on the token
DRF JWT Token Authentication
One Token per session
Expiry timestamp on each token
Database access
DRF's builtin Token Authentication
Database access to fetch the user associated with the token
Verify user's status
Authenticate the user
DRF JWT Token Authentication
Decode token (get payload)
Verify token timestamp (expiry)
Database access to fetch user associated with the id in the payload
Verify user's status
Authenticate the user
Pros
DRF's builtin Token Authentication
Allows forced-logout by replacing the token in the database (ex: password change)
DRF JWT Token Authentication
Token with an expiration time
No database hit unless the token is valid
Cons
DRF's builtin Token Authentication
Database hit on all requests
Single token for all sessions
DRF JWT Token Authentication
Unable to recall the token without tracking it in the database
Once the token is issued, anyone with the token can make requests
Specs are open to interpretations, no consensus on how to do refresh
Reference: Django : DRF Token based Authentication VS JSON Web Token
I'd like to leave my answer after I solved in my way through my long research and study. My solution is quite simple.1. set DRF session authentication enable. Adding some code in setting.py
REST_FRAMEWORK = {
# ...
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
}
2. add 'credentials: "include"' into fetch code to use already logged in session cookie for authentication.
await fetch(API_URL, {
credentials: "include"
})
this solution solved my case.

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