Hello there ๐,
Today I am going to talk about a recent feature I struggled to implement on Django Rest Framework ( DRF). I aimed to prevent multiple device login, it may seem easy but it wasn't for a week. I tackled this for a week. I got lots of ideas, code, etc. None worked and it got so bad that the more I tried, the more I caused pain to my codebase. I cried a lot ๐ but in the end, I pulled through with the help of a friend so I will also share my knowledge in this article.
Let's start ๐
1. LoginView
The LoginView control displays different Web site content templates (or "views") for different users, based on whether the user is authenticated and, if so, which Web site roles they belong to.
The template stored in this view is shown to the user when they haven't logged in. The LoginView control manages to switch among the various templates once you assign templates.
Below is an example of what a LoginView Django code looks like:
Views.py
#loginView
from django.contrib.auth.views import LoginView
class AdminLogin(LoginView):
template_name = 'LoginView_form.html'
Template_name: the template that would display the login form.
Urls.py
#LoginView
path('login/', AdminLogin.as_view(), name="login")
Settings.py
LOGIN_REDIRECT_URL = 'home' # URL redirecting after a successful authentication
This redirects the user (after successfully logging in) to a homepage.
You created a class-based view and called LoginView to override the built-in login system by Django. If your code works you should see your homepage after you click the login button.
2. dj_rest_auth.views
The dj_rest_auth.views handle the authentication in DRF (Django Rest Framework) and it works especially well with SPAs (e.g React, Vue, Angular), and Mobile applications. It provides endpoints for:
User registration with optional activation
Login and Logout
Retrieve and update Django User model
Password change
Password reset via e-mail
Social media auth authentication.
Okay, now we what LoginView and dj_rest_auth.views are and how it works. I will now explain how to solve my problem.
Import LoginView
First, I imported LoginView from dj_rest_auth.views. I wrote it like this:
from dj_rest_auth.views import LoginView
Create class-based view
Next, I created a class-based view in my views.py and called the original serializer for LoginView. For the class-based view, I set the token to reset each time a user logs in and the old token will be deleted and the new token will be returned through the endpoint and saved on the database.
class CustomAuthToken(LoginView):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(
data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data["user"]
user.auth_token.delete()
token, created = Token.objects.get_or_create(user=user)
return Response(
{
"key": token.key,
"message": "Old Token Deleted"
},
status=status.HTTP_200_OK
)
Before it changes the user's token, it first validates that said user is registered and saved on the database. That is what user = serializer.validated_data["user"] does.
The next line deletes the old token while the next line creates a new token and saves it.
return Response: returns the new token and a message that say old key deleted
Urls.py
Next is to add to the urls.py of your project's file
path('auth/signin/', CustomAuthToken.as_view(), name='customsignin')
The above code created a custom authentication backend code that deletes a user token after a user signs in.
That's all. I just explained how to create a custom backend authentication that changes user token after login/sign in.
Keep in touch:
Thanks for reading till the end โค๏ธ.
You can contact me via email and/or Discord:
Email - iroegbusophia3@gmail.com
Discord - Sophyia#8929