Authentication Mechanisms | Django-Rest-Framework | Part-1
Deep into Authentication
Holla Forks! I Hope summers are going well.
Today we are going to talk about creating API’s using Django. I’m an absolute beginner and started learning about Django a few days back, so we will more focus on making things work rather than understanding how things are exacting working.
I was little amazed when I found out that django-rest-framework is a third-party library and not provided by Django itself. Did you know that??
Here I will skip all the installing part and setting up things (if you are facing a problem this could be [helpful]). Moving on there are some types of authentication that can be used with rest-framework we will be using Token based authentication. In that, a unique token is generated for every user which would be included in every request that a user makes, If you wish to learn more about on what is token based authentication etc. refer [here].
First, we would need to change settings.py, Add these lines to include rest_framework classes for authentication this would be an override to normal Django classes.
settings.py
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication',), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated',)}
Here: IsAuthenticated class will be used to check the authentication status of the user.
And, you can create a new app to manage all the user model that will handle user authentication, registration etc or in some other app, I will leave that part to you.
Let’s create an API endpoint from which we can register new users.
path("register/", UserRegistrationAPIView.as_view(), name="register_user"),
Include this to your urls.py. Here UserRegistrationAPIView is a View which will handle all the registrations and endpoint would be /register/
Views.py
class UserRegistrationAPIView(CreateAPIView): authentication_classes = ()
permission_classes = () serializer_class = UserRegistrationSerializer def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) user = serializer.instance token, created = Token.objects.get_or_create(user=user) data = serializer.data data["token"] = token.key headers = self.get_success_headers(serializer.data) return Response(data, status=status.HTTP_201_CREATED, headers=headers) .
serializers.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_passwordclass UserRegistrationSerializer(serializers.ModelSerializer): email = serializers.EmailField(required=True,validators= . [UniqueValidator(queryset=User.objects.all())]) username = serializers.CharField(max_length=32,validators=[UniqueValidator(queryset=User.objects.all())]) password = serializers.CharField(min_length=4, max_length=100,write_only=True) confirm_password = serializers.CharField(min_length=4, max_length=100,write_only=True)class Meta: model = User fields = ("id", "username", "email", "password", "confirm_password", "date_joined") def create(self, validated_data): user = User.objects.create( email=validator_data['email'], username=validator_data['username'], password=make_password(validator_data['password'])) return user def validate(self, attrs): if attrs.get('password') != attrs.get('confirm_password'): raise serializers.ValidationError("Those passwords don't match.") return attrs
We will have added checks like email should be unique along with username and password confirm password should be equal and should match.
If you are new to Django-rest-framework then serializers WTF is that
Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into
JSON
,XML
or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
In easy words, Serializers are used to convert the objects of the database in such a format that can be accessed using API’s.
Q.) What is make_password()?
Ans.) make_password() is used to hash password which is very important. No one saves the password in plain text nowadays other than Facebook.
The registration endpoint is available to register new users in my case at
localhost:8000/api/account/register/
why not try it out, I will use postman to check my API
All the checks are working: In image, it’s visible that I have only passed email-id which is not unique as some other user already using this email and other fields are empty. Now let’s try again with all details
Holla, everything is working we have got token here we should store this is front-end and use this for all the requests that we want to make to access all endpoints.
BUT BUT BUT What about login?
For login, the Mechanism would be to have an endpoint which will take username, password and return token. Every time user logout from front-end you will delete token from front-end.
So, For login django-rest-framework provide a function which can be used. Add this to your urls.py
from rest_framework.authtoken import views
urlpatterns = [
url(login/', views.obtain_auth_token)
]
But, we should add one more thing that is deleting token after some time and create another to improve security. This library can be used to do that easily refer [here].
That will do our login and registering but where is validation model?
Django-rest-framework provides some @permission_classes same as @login_required in Django here is a simple example:
@api_view(['GET'])@permission_classes((IsAuthenticated, ))def ListUsers(request, format=None): contete = {'status':'request permitted bro'} return Response(contete)
api_view([‘GET’]) says that this function will only accept get requests.
permission_classes((IsAuthenticated, )) is used to check the authentication of the request if it’s authenticated it will provide or it will raise an error as:
{
"detail": "Authentication credentials were not provided."
}OR{
"detail": "Invalid token."
}
Yeaah!! We have created a simple login and signup end points along with authentication checks too.
Some points to keep in mind
- This is my approach to do this, there may be other ways which may be even better.
- This blog post is written for people who already have a basic idea of Django and django-rest-framework.
- I’m still in the learning phase and there may be some problems in code, please comment below so that I could fix them for others and for me.
Thanks for reading I would be sharing more on Django-Rest-Framework and ReactJs, so don’t forget to follow this account.
Part-2 is available here: https://medium.com/@omi10859/authentication-routering-and-much-more-reactjs-part-2-4fcecea1d233