I want to make a very custom login system and I'm failing to receive the user instance when the token is sent within the headers
. I have number of APIs which need to work with and without users logged in and need to access the user.id
(primary key). In my custom Login
, I want to get the user instance and do a custom check. But I can never access the user even though the token is created and is being sent within the header.
I'm sending the token in header within Postman:
"Authorization": "Token {{token}}"
settings.py:
.....
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'corsheaders',
'pgtrigger',
'rest_framework',
'rest_framework.authtoken',
'myapp'
]
.....
AUTH_USER_MODEL = "myapp.User"
.....
login.py:
from typing import Any
from django.db.models import Q
from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.request import Request, QueryDict
from rest_framework.views import APIView
import bcrypt
from myapp.util.functions import contains, API_CallBack
from myapp.util.classes import Error
from myapp.models.user.user import User
class Endpoint(APIView):
authentication_classes = [BasicAuthentication, SessionAuthentication]
permission_classes = [AllowAny]
def post(self, request: Request):
# --------------------
# Get and Check Data
# --------------------
print()
print(request.user) // NOT GETTING THE USER HERE
print()
par: QueryDict = request.data
if (
not contains(par) or
not (par.keys() >= { "id", "password" })
): return API_CallBack(Error("gRXIQWhkb6"))
_return = Error("eKKld8iqrz")
try:
_return = Login(request, par["id"], par["password"])
except Error as e: _return = e
return API_CallBack(_return)
def Login(request: Request, id: str, password: str) -> dict[str, str]:
# -------------------------------
# Check and Format Data
# -------------------------------
# req.session.modified = True
if (
not contains(request, id, password) or
Token.objects.filter(user = request.user).exists()
): raise Error("ulxdQrfrP2")
# -------------------------------------
# Execute Queries and Perform
# -------------------------------------
try:
user: User = User.objects.filter(
Q(account_name__exact = id) | Q(email__exact = id)
).get()
# Start Session
if bcrypt.checkpw(password.encode("UTF8"), user.password.encode("UTF8")):
token: Token = Token.objects.create(user = user)
return { "token": token.key }
else:
raise Error("tSqmORm1y5", 404, "empty", "No record found with inserted inputs")
except User.DoesNotExist:
raise Error("h0lddS4Jtn", 404, "empty", "No record found with inserted inputs")
except Exception as e:
print(f"\n{str(e)}\n")
raise Error("SwZu4K4N1p", message="Token already exists")
I think that user.is_active
may be False
.
It appears that the specific error message you are seeing is raised directly from the TokenAuthentiation
or BasicAuthentication
class.
if not token.user.is_active:
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
Session auth, to my surprise, doesn't raise this.