Unable to get user id with token by django rest framework? - django

I am using django Django=2.1.7 and rest framework djangorestframework=3.9.2 This is my url for login
path('rest-auth/', include('rest_auth.urls')),
After authentication I got token but I need user id too. I tried to override the post method of rest_framework.authtoken.views.py file with the following code
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
context = {
'token': token.key,
'user': user.id
}
return Response({'context': context})
Please help me figure out how to get user id with the token. This is my college project.
Note: I find many answers on stack overflow but none is helpful.

Use this Django RestFramework token authentication in order to use authentication. Here you can see how to authenticate, however if you want to use token authentication by default for all views you should add it in settings.py file as :
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework.authentication.TokenAuthentication',
...
),
}
or you should add it manually to views which requires token authentication. And in this views you can get authenticated user as request.user or self.request.user.
from rest_framework.authentication import TokenAuthentication
class ViewSetName(ViewSet):
authentication_classes = [TokenAuthentication]

Related

What is the use of token return after login or registration from django-rest-knox?

Hy there,
I work on project where I used django-rest-knox for token authentication. I have doubt that
1.How token be used that has return while registering and login.
(
when i pass token in postman as like,
in header section
Authentication Token abcjdkkfjjrhehrjlajn#kfjdk
) this doesnot work
2.when i call logout and logoutall endpoint it say,
{
"detail": "Authentication credentials were not provided."
}
even though i pass all correct credentials.
Here is the code that i follow,
in setting.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
'knox.auth.TokenAuthentication',
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",)}
REST_AUTH_TOKEN_MODEL = 'knox.models.AuthToken'
REST_AUTH_TOKEN_CREATOR = 'users.authentication.create_knox_token'
REST_AUTH_SERIALIZERS = {
'USER_DETAILS_SERIALIZER': 'users.serializers.CustomUserSerializer',
'TOKEN_SERIALIZER': 'users.serializers.KnoxSerializer'
}
in urls.py
path('auth/register/',KnoxRegisterView.as_view(),name='register'),
path('auth/login/',KnoxLoginView.as_view(),name='login'),
path('api/auth/logout/',knox_view.LogoutView.as_view(),name='knox_login'),
path('api/auth/logoutall/',knox_view.LogoutAllView.as_view(),name='knox_alllogin'),
in authentication.py
from knox.models import AuthToken
def create_knox_token(token_model, user, serializer):
token = AuthToken.objects.create(user=user)
return token
in serializers.py
class KnoxSerializer(serializers.Serializer):
"""
Serializer for Knox authentication.
"""
token=serializers.CharField()
user = CustomUserDetailsSettingsSerializer()
in views.py
class KnoxRegisterView(RegisterView):
def get_response_data(self, user):
return KnoxSerializer({'user': user, 'token': self.token}).data
def perform_create(self, serializer):
user = serializer.save(self.request)
self.token = create_knox_token(None, user, None)
complete_signup(self.request._request, user, allauth_settings.EMAIL_VERIFICATION, None)
return user
class KnoxLoginView(LoginView):
def get_response(self):
serializer_class = self.get_response_serializer()
data = {
'user': self.user,
'token': self.token
}
serializer = serializer_class(instance=data, context={'request': self.request})
return Response(serializer.data, status=200)
I'm not sure but I think your problem is that you need to override the login view so it doesn't request authentication. Usually the rest framework is setup like this:
# setting.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
So, your framework thinks it need authentication to ALL views, including the login view (which is silly of course).
The solution is to rewrite the login view as the documentation note:
If it is your only default authentication class, remember to overwrite knox's LoginView, otherwise it'll not work, since the login view will require a authentication token to generate a new token, rendering it unusable.
Try to add to your login view:
class KnoxLoginView(LoginView):
...
permission_classes = (permissions.AllowAny,)
...

JWT authentication returns AnonymousUser in Django Rest Framework with SimpleJWT

I am opening this question as a last resort.
I am learning JWT and want to implement it on my django app. I didn't have any issues regarding Basic auth and Token auth, but JWT doesn't authenticate my user...
This is my settings.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
'api.permissions.AdminOrTeacherOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
}
This is my view:
class StudentList(APIView):
authentication_classes = []
permission_classes = [AdminOrTeacherOnly]
def get(self, request, format=None):
students = Student.objects.all()
serializer = StudentListSerializer(students, many=True)
if not serializer.data:
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.data, status=status.HTTP_200_OK)
This is my AdminOrTeacherOnly permission class:
class AdminOrTeacherOnly(permissions.BasePermission):
"""
Object-level permission to only allow teachers of a student to edit.
Assumes the model instance has an `owner` attribute.
"""
message = 'Only admin or teacher can edit student detail.'
def has_permission(self, request, view):
# Only teacher and/or admin user will be able to,
# edit and/or list this view.
is_staff = bool(request.user and request.user.is_staff)
is_teacher_group = str(request.user.groups.all().first()) == 'teacher'
return is_staff or is_teacher_group
I am able to get refresh and access token successfully:
Then, I am adding this to Headers as follows and send a request:
On debugger, when it enters the permission class:
Here, request.user returns <django.contrib.auth.models.AnonymousUser object at 0x104f5afd0>
I don't know what I am missing. Looked at related questions but couldn't find anything helpful regarding the SimpleJWT.
You're overriding authentication_classes here:
class StudentList(APIView):
authentication_classes = []
Add JWTAuthentication to that list.

How can I bypass drf Token Authentication when using firebase for authentication in django?

I need to sign in a user using firebase from my django app.I have done what I think I needed to do but I seem to be missing something.I am using the pyrebase library.I have created a user on firebase and now I need to sign them in.
I am posting the email and password on Postman and I get the 'idToken' and 'refreshToken', which means the user gets authenticated on firebase.But this only works when I use the drf Token authentication(DEFAULT AUTH CLASSES) and authorization token of a user previously created on django admin. What am I missing so that I can authenticate the user without the drf token authentication?
views.py
config = {
"apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
"authDomain": "xxxxx.firebaseapp.com",
"databaseURL": "https://xxxxxxxxx-default-rtdb.firebaseio.com",
"storageBucket": "xxxxxxxxx.appspot.com",
}
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
class Auth(APIView):
def post(self, request, format=None):
email = "xxxx#gmail.com"
password = "xxxx"
user = auth.sign_in_with_email_and_password(email, password)
return Response(user)
Settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
}
Yeah so basically, you don't need any authorization in any of the authentication views. Since you have a global default of IsAuthenticated, you need to overwrite the permission_classes in the View.
class Auth(APIView):
permission_classes = []
def post(self, request, format=None):
...

How does Django RESTful Framework get user model from token from HTTP header?

I'm building my Django RESTful Framework to retrieve and post data for Mobile. I'm using Django-rest-auth (which is just all-auth with RESTful functionality; more info : http://django-rest-auth.readthedocs.io/en/latest/).
How does Django RESTful Framework (or Django) finds user's model when mobile sends user's token in HTTP header?
For instance:
HTTP METHOD: POST
headers : Authorization eyl3of9iskjfpjowpefjsopeff (This is token and random string)
body : {
post_title: "This is my first post"
post_content: "This is the content"
}
This is my setting:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
# 'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
This is where I want to find a user model :
class CreatePost(generics.CreateAPIView):
def get_queryset(self, **kwargs):
owner = User.objects.filter(user= ##) # right here!
post_title =
post_content =
Or any other approach suggested?
Usually, your Token is simply a Django model, which is stored in your database.
It has a OneToOne relation to your User model and that's simply how they are related (in rest_framework.authtoken). You can see it in DRF source.
A direct examle:
from rest_framework import generics
from rest_framework import status
from rest_framework.authtoken.models import Token
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# You can directly import your Token model for usage
from .serializers import UserLoginSerializer
class UserLogin(generics.CreateAPIView):
serializer_class = UserLoginSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, _ = Token.objects.get_or_create(user=user)
# Here you either get a Token if it exists in your db
# Or generate it if it is not created yet
# See that you directly get the token with your user:
# Token.objects.get_or_create(user=user)
# You can also access it vice-versa: token.user <-> user.token
# Because it is a OneToOne relation
response_data = {
'id': user.id,
'token': token.key
}
headers = self.get_success_headers(serializer.data)
return Response(response_data, status=status.HTTP_200_OK, headers=headers)
Note: If you are using JWT, have a look at how a token is linked with the user.
In your case:
class CreatePost(generics.CreateAPIView):
def get_queryset(self, **kwargs):
owner = self.request.user
# Are you sure you don't want to get the current request user?
# Why you should filter with token?
post_title = ...
post_content = ...
Your authentication classes (in your case, JSONWebTokenAuthentication, it automatically sets request.user to the correct one and you can access it in your views).

Unabe to get token from DRF get-token api

my custom signup api
from rest_framework import viewsets
from rest_framework import serializers
class SignupSerializer(serializers.Serializer):
email = serializers.EmailField(required=True)
password = serializers.CharField(required=True, write_only=True)
def validate_email(self, val):
try:
User.objects.get(username=val)
raise serializers.ValidationError("Email-ID already Exist")
except User.DoesNotExist:
return val
class SignupView(viewsets.ModelViewSet):
serializer_class = SignupSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.data
email = data.get('email')
password = data.get('password')
u = User(email=email, username=email)
u.set_password(password)
u.save()
data = {
'message': 'Successfully Created!',
'data': {'id': u.id, 'email': email},
}
return Response(data)
Toekn get api
from rest_framework.authtoken import views
urlpatterns = [
url(r'^api-token-auth/', views.obtain_auth_token),
]
when I hit signup api, it returns the success response, I mean
{
'message': 'Successfully Created!',
'data': {'id': 1, 'email': 'xyz#gmail.com'} }
but when I try to generate/get token for this user using above token api, it says ..invalid credentials?
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
however if I create a user using management command createsuperuser and use same api to get token it works?
is there someting wrong in signup api?
You should remove write_only=True from your serializer. that would fix the error.
The Error message actually tells you that your request is not able to reach the view, this happens because one of the middlewares raises an error.
The easiest (but pbly not very secure) solution would be to return the API token on successful signup, or to add another View with a login (which returns an token).
For a definite answer you would need to provide more information like the configuration for your Authentication Backends.
You can find here more Informations about Authentication in DRF
http://www.django-rest-framework.org/api-guide/authentication/#how-authentication-is-determined