36
loading...
This website collects cookies to deliver better user experience
from django.conf import settings
from django.db import models
from rest_framework.authtoken.models import Token as AuthToken
class Token(AuthToken):
key = models.CharField("Key", max_length=40, db_index=True, unique=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name="auth_token",
on_delete=models.CASCADE,
verbose_name="User",
)
accounts
, which is where I usually define my custom user model as well.REST_AUTH_TOKEN_MODEL = "accounts.models.Token"
import datetime
import pytz
from django.utils import timezone
def custom_create_token(token_model, user, serializer):
token = token_model.objects.create(user=user)
utc_now = timezone.now()
utc_now = utc_now.replace(tzinfo=pytz.utc)
token.created = utc_now
token.save()
return token
accounts/utils.py
.REST_AUTH_TOKEN_CREATOR = "accounts.utils.custom_create_token"
INSTALLED_APPS
:INSTALLED_APPS = [
...
'rest_framework.authtoken' # <== This line should be removed
]
python manage.py makemigrations accounts
accounts
here because our model resides in accounts
app, change it accordingly as per your implementation. This will create the migrations, now migrate using:python manage.py migrate accounts
NOTE : If you had any tokens previously created using default Token model, then those tokens will become invalid later as we will be switching out the Authentication Backend as well.
import datetime
import pytz
from django.conf import settings
from django.utils import timezone
from rest_framework.authentication import TokenAuthentication
from rest_framework.exceptions import AuthenticationFailed
from accounts.models import Token
class ExpiringTokenAuthentication(TokenAuthentication):
"""
Expiring token for mobile and desktop clients.
It expires every {n} hrs requiring client to supply valid username
and password for new one to be created.
"""
model = Token
def authenticate_credentials(self, key, request=None):
models = self.get_model()
try:
token = models.objects.select_related("user").get(key=key)
except models.DoesNotExist:
raise AuthenticationFailed(
{"error": "Invalid or Inactive Token", "is_authenticated": False}
)
if not token.user.is_active:
raise AuthenticationFailed(
{"error": "Invalid user", "is_authenticated": False}
)
utc_now = timezone.now()
utc_now = utc_now.replace(tzinfo=pytz.utc)
if token.created < utc_now - settings.TOKEN_TTL:
raise AuthenticationFailed(
{"error": "Token has expired", "is_authenticated": False}
)
return token.user, token
accounts/authentication.py
.REST_FRAMEWORK
config in your project settings as follows:REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication", # Replace this line
"accounts.authentication.ExpiringTokenAuthentication", # <-- with this line
"rest_framework.authentication.SessionAuthentication",
),
# ...
}
settings.TOKEN_TTL
, which is another functionality that I have added to allow configuring the Token's Lifespan or Token - Time to Live through project settings instead of setting it to a fixed value.import datetime
TOKEN_TTL = datetime.timedelta(days=15)