I have a basic django rest service, which
I want to add jwt authentication on top of it. If I follow the tutorial I would need to add a new url named "api-token-auth" in project's urls.py. But, I don't want to add this new url and want my register call to send a token in response.
Here's my code:
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
def create(self, validated_data):
user = User(
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
def update(self, instance, validated_data):
instance.set_password(validated_data['password'])
instance.save()
return instance
class Meta:
model = User
fields = ('url', 'username', 'password')
lookup_field = 'username'
write_only_fields = ('password',)
views.py
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.exclude(is_superuser=1)
serializer_class = UserSerializer
lookup_field = 'username'
After verifying the credentials, the server issues two JSON Web Tokens to the user. One of them is an Access Token and the other is a Refresh Token. The frontend of your application then stores the tokens securely and sends the Access Token in the Authorization header of all requests it then sends to the server.
Request an Auth Token in Django REST FrameworkThe Django REST Framework will provide an endpoint so that the user can request a Token for authentication with their password and username. It won't handle GET requests. It will inform you to use POST request with username and password.
Question 1: To generate tokens manually on registration you can define and make use of a method like this:
import jwt
from rest_framework_jwt.utils import jwt_payload_handler
def create_token(user):
payload = jwt_payload_handler(user)
token = jwt.encode(payload, settings.SECRET_KEY)
return token.decode('unicode_escape')
you can add this method to the view and generate the token once the user has been registered and return it in the response.
Question 2: JWT tokens do not need to be stored in the database. You can read more about how JWT works at http://jwt.io/.
Question 3 and 4: To use tokens to limit access to a specific view, especially an APIView or one of its subclasses or a view provided by Django Rest framework, you need to specify the permission classes. for example:
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
Question 5: One potential loophole while working with Django Rest Framework is the default permissions that you setup from the settings of your application; if for example you AllowAny
in the settings it'll make all the views publicly accessible unless you specifically override the permission classes in each view.
The Accepted answer has some code that generates token but it doesn't show how to integrate it in serializer/view. Also not sure that manual jwt.encode
is a good modern way of doing this if we already have jwt_encode_handler
to do this. You can create SerializerMethodField
and create tokens there:
token = serializers.SerializerMethodField()
def get_token(self, obj):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(obj)
token = jwt_encode_handler(payload)
return token
Then add token
field to Meta.fields
.
Working Example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With