In this part we will see about authentication for api
Django comes with a pre-build authentication framework which you can see more details here https://docs.djangoproject.com/en/2.2/topics/auth/
Even in our current project we had create one user in previous blog to test our the Browsable API
If you login to into admin system i.e http://127.0.0.1:8000/admin/ you will see “Users”, “Groups” . So django maintains full users, groups management system pre-build internally.
By default django uses “Session” and “Basic” auth which are used mainly in web based system. But for rest api’s we need “token” auth which DRF provides.
https://www.django-rest-framework.org/api-guide/authentication
Read above properly its quite self explanatory. Let’s see this in practice by creating login/registration routes
Above will require help from https://docs.djangoproject.com/en/2.2/topics/auth/default/ to understand django user object
These are code changes required, first lets setup then auth app
//settings.py
....
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication'
)
}
....
INSTALLED_APPS = [
...
'rest_framework.authtoken'
]
next on command line
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
next lets add a route
from rest_framework.routers import DefaultRouter
from todo.views import TodoViewSet, UserAuth
from django.urls import path, include, re_path as url
"""
FULL CRUD OPERATION FOR TODO
"""
router = DefaultRouter()
"""
FULL CRUD OPERATION FOR TODO
"""
router.register(r'todo', TodoViewSet, basename='todo')
urlpatterns = [
url(r'^login/$', UserAuth.as_view()),
]
urlpatterns = urlpatterns + router.urls
next let’s setup View
P.S. some import's have been missed out intentionally so that you explore official docs better and find out
class UserAuth(APIView):
"""
Manager User Login and other things
"""
def post(self, request):
"""
login
"""
user = authenticate(username=request.data.get("username"), password=request.data.get("password"))
if user is not None:
# A backend authenticated the credentials
token = Token.objects.create(user=user)
print(token.key)
print(user)
return Response(token.key)
else:
# No backend authenticated the credentials
return Response([], status=status.HTTP_401_UNAUTHORIZED)
Now if you run this on postman you should get token
Next lets create a new route for registration
class UserRegister(APIView):
"""
Create user
"""
def post(self, request):
user = User.objects.create_user(
username=request.data.get("username"),
email=request.data.get("email"),
password=request.data.get("password"))
user.save()
if user is not None:
token = Token.objects.create(user=user)
print(token.key)
print(user)
return Response(token.key)
else:
return Response([], status=status.HTTP_400_BAD_REQUEST)
Token is generated
Also in admin new user is added as well
Next let’s try to login with this same user
when we login with user getting an error
This error is coming because token already exists for this user in database. So when it tries to create new token with same user_id it gives an error
If you look at the admin token already exists for users
To fix the above issue here is the updated route
class UserAuth(APIView):
"""
Manager User Login and other things
"""
def post(self, request):
"""
login
"""
user = authenticate(username=request.data.get(
"username"), password=request.data.get("password"))
if user is not None:
# A backend authenticated the credentials
try:
token = Token.objects.get(user_id=user.id)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
return Response(token.key)
else:
# No backend authenticated the credentials
return Response([], status=status.HTTP_401_UNAUTHORIZED)
Now, next lets add a route to fetch user data and in this we will check permission
...
from rest_framework.permissions import IsAuthenticated
...
//views.py
class UserAuth(APIView):
"""
Manager User Login and other things
"""
permission_classes = (IsAuthenticated,)
def get(self, request):
ser = UserSerializer(request.user)
return Response(ser.data)
We need to define a UserSerializer to send back model data
//serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
Rest we can add change password, update user etc as well all function details mentioned here https://docs.djangoproject.com/en/2.2/topics/auth/default/
Here is an small example of how of authentication and permission in django work with also associating a user with a snippets in case of this example so do check it
https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/
Groups/Permissions
Let’s look at user groups/permissions , till now we just looked a basic login/registration. Let’s see how we can manager groups/permission supposed we have 3 groups
- Admin
- Employee (custom group doesn’t exist)
- Guest (no logged)
Let’s see more about this in next blog