Problem With Jwt Authentication In Django-rest-framework
Solution 1:
I think your procedure is wrong. According to Knox documents, You need to give an access permission login endpoint. But you did not give permission to access your login endpoint. So your login endpoint looks like this,
# views.py from django.contrib.auth import login
from rest_framework import permissions
from rest_framework.authtoken.serializers import AuthTokenSerializer
from knox.views import LoginView as KnoxLoginView
classLoginView(KnoxLoginView):
permission_classes = (permissions.AllowAny,)
defpost(self, request, format=None):
serializer = AuthTokenSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
returnsuper(LoginView, self).post(request, format=None)
# settings.py
REST_KNOX = {
'USER_SERIALIZER': 'knox.serializers.UserSerializer',
}
If you use the user serializer in your setting you get token with the username of the requesting user like bellow
{"user":{"username":"admin"},"token":"00bd2a5e517800b75a8f36bbf3baea4c839169108b25a5a5ea599a4ecda974c0"}
More details here. Knox
Solution 2:
Hi it seems that you are using knox which is not exactly the same, but in essence it is similar. Your view seems protected probably because of your DEFAULT_PERMISSION_CLASSES
settings.
If you to be able to login via this view you'd have to set
permission_classes = [AllowAny, ]
on your view.
However I would not do that since this is a hack. (I know I have been through it and we red the same article).
The correct way to do it is to define the User serializer in the Django Configuration/Settings file, so that you can retrieve the info you want when you log in.
REST_KNOX = {
'USER_SERIALIZER': 'auth.serializers.UserRetrieveSerializer'
}
Then simply extend the default login view and use basic auth
as authentication class.
from knox.views import LoginView as KnoxLoginView
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated
classLoginAPI(KnoxLoginView):
"""
Login endpoint.
"""
authentication_classes = [BasicAuthentication, ]
permission_classes = [IsAuthenticated, ]
And for all the other views you could use knox.auth.TokenAuthentication
.
And that's it...
Relevant code for testing it is:
import base64
defget_basic_auth_header(username, password):
return'Basic %s' % base64.b64encode(
('%s:%s' % (username, password)).encode('ascii')).decode()
from rest_framework.test import APITestCase
classMyTestCase(APITestCase):
username = 'foo'
password = 'bar'deftest_login(self):
# Add basic auth credentials
self.client.credentials(
HTTP_AUTHORIZATION=get_basic_auth_header(
self.username, self.password))
etc...
In your urls.py
from knox import views as knox_views
from .views import LoginAPI
...
url(r'^login/$', LoginAPI.as_view(), name='knox_login'),
url(r'^logout/$', knox_views.LogoutView.as_view(), name='knox_logout'),
url(r'^logoutall/$', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
...
Solution 3:
Where do you get your error "credentials were not provided"? If it is the case when calling the route by hand in the browser, I think it is fine (at least I get it, while data is loaded properly in my tables etc.)
I had the problem that authentication with knox token did not work on Safari and on iPad. The reason was that I had a trailing slash in my routes and this caused 301 - Moved permanently responses with subsequent redirects, which obviously did not forward the token. I removed the trailing slashes and everything was fine then.
By the way: Using
permission_classes = (permissions.AllowAny,)
does not seem to be right, I think it more or less contradicts the use of tokens. It should be
permission_classes = [permissions.IsAuthenticated]
Solution 4:
If you are deeploying to the Apache then add the WSGIPassAuthorization On to the 000-default.conf file. That solved my issues. See: https://www.django-rest-framework.org/api-guide/authentication/
Post a Comment for "Problem With Jwt Authentication In Django-rest-framework"