Reputation: 31
I have question related with Django . I am using Knox Token Authentication to generate tokens for every user when he log in on the page.
Now I want to use that token for every request that will send so I can get the corresponding user for the token. Also I am using custom function example def dashboard(request)
in Django for every URL route.
I have see on youtube that there are option to get user from token but is not with functions
class UserAPI(generics.RetrieveAPIView):
permission_classes = [
permissions.IsAuthenticated,
]
serializer_class = UserSerializer
def get_object(self):
return self.request.user
So is there a whey to get the corresponding user from a token within a custom function
Upvotes: 2
Views: 2288
Reputation: 66
I think the below is a better and more secure way to implement it
from knox.auth import TokenAuthentication
auth = TokenAuthentication()
user = auth.authenticate_credentials(token)[0]
Upvotes: 0
Reputation: 381
Great, I figured out in hours that knox doesn't come with full token_key stored in database.
Real token we can get is something like:
a512529e7ffceaa8406ceb616d088b3422ad15811a5eb470e8f4c4896c9aa649
In database token_key is stored by default a512529e
. 8 digits.
Filter objects using this:
knox_object = AuthToken.objects.filter(token_key__startswith=token[:8]).first()
Then get user object
knox_object.user.username
Or you can use this, faster
from knox.settings import CONSTANTS
knox_object = AuthToken.objects.filter(token_key=token[:CONSTANTS.TOKEN_KEY_LENGTH]).first()
From the knox source codes
class CONSTANTS:
'''
Constants cannot be changed at runtime
'''
TOKEN_KEY_LENGTH = 8
DIGEST_LENGTH = 128
SALT_LENGTH = 16
def __setattr__(self, *args, **kwargs):
raise Exception('''
Constant values must NEVER be changed at runtime, as they are
integral to the structure of database tables
''')
CONSTANTS = CONSTANTS()
You can see TOKEN_KEY_LENGTH
is of 8 digits.
I wrote a simple function to do that
from knox.models import AuthToken
from knox.settings import CONSTANTS
def get_user_from_token(token):
objs = AuthToken.objects.filter(token_key=token[:CONSTANTS.TOKEN_KEY_LENGTH])
if len(objs) == 0:
return None
return objs.first().user
Life be easier now. :)
You may try my fork. If you just simply want to add @smart_token_user
before any GET/POST/PUT/... methods.
https://github.com/xros/django-rest-knox
Just git clone, and pip install ./
I wrote a decorator.
With this,
in our app views.py
we can easily get user object by doing so,@smart_token_user
will modify the request handler. We can have a request.user
attr only once the token is valid. And all invalid attempts will be thrown out with HTTP 401 Unauthorized response.
Life can be easier with this decorator.
from knox.models import smart_token_user
class CheckUserEmail(generics.RetrieveAPIView):
permission_classes = (IsAuthenticated,)
@smart_token_user
def get(self, request):
return Response({
"username": request.user.username,
"email": request.user.email,
"password": request.user.password,
}, status=status.HTTP_200_OK)
Or use this like original if you want: authentication_classes = (TokenAuthentication,)
class CheckUserEmail(generics.RetrieveAPIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
def get(self, request):
return Response({
"username": request.user.username,
"email": request.user.email,
"password": request.user.password,
}, status=status.HTTP_200_OK)
Upvotes: 0