Skip to content

Instantly share code, notes, and snippets.

@cb109
Last active January 25, 2023 08:42
Show Gist options
  • Select an option

  • Save cb109/c81bb35ed3dcfe093d5a5775f31e2ea2 to your computer and use it in GitHub Desktop.

Select an option

Save cb109/c81bb35ed3dcfe093d5a5775f31e2ea2 to your computer and use it in GitHub Desktop.
Setting up DRF Token authentication with basic expiration
from datetime import timedelta
from django.conf import settings
from django.utils import timezone
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed
def is_token_expired(token):
min_age = timezone.now() - timedelta(
seconds=settings.TOKEN_EXPIRED_AFTER_SECONDS)
expired = token.created < min_age
return expired
class ExpiringTokenAuthentication(TokenAuthentication):
"""Same as in DRF, but also handle Token expiration.
An expired Token will be removed and a new Token with a different
key is created that the User can obtain by logging in with his
credentials.
Raise AuthenticationFailed as needed, which translates
to a 401 status code automatically.
https://stackoverflow.com/questions/14567586
"""
def authenticate_credentials(self, key):
try:
token = Token.objects.get(key=key)
except Token.DoesNotExist:
raise AuthenticationFailed("Invalid token")
if not token.user.is_active:
raise AuthenticationFailed("User inactive or deleted")
expired = is_token_expired(token)
if expired:
token.delete()
Token.objects.create(user=token.user)
raise AuthenticationFailed("Token has expired")
return (token.user, token)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'myproject.authentication.ExpiringTokenAuthentication',
)
}
@yerkbn

yerkbn commented Oct 10, 2018

Copy link
Copy Markdown

thank you

@ramsrib

ramsrib commented Nov 4, 2018

Copy link
Copy Markdown

        if expired:
            token.delete()
            Token.objects.create(user=token.user)
            raise AuthenticationFailed("Token has expired")

Why do you create a new token when it's expired?

@cb109

cb109 commented Mar 11, 2019

Copy link
Copy Markdown
Author

@ramsrib To ensure an expired Token can not be used to authenticate ever again. Of course that's not the way you have to do it, this gist is merely a starting point, you can implement your own logic, like refreshing the token.

@SoundWaveX81

Copy link
Copy Markdown

@cb109 you can rewrite the authenticate_credentials method to make short your code using the father class' autheticate_credentials method

def authenticate_credentials(self, key):
    user, token = super().authenticate_credentials(key)
    if self.is_token_expired(token):
        token.delete() # or whatever logic you want 
        raise AuthenticationFailed("Token has expired")
    return user, token

@cb109

cb109 commented Jan 25, 2023

Copy link
Copy Markdown
Author

@SoundWaveX81 That's indeed shorter, good point. Back then I copied the full method to see how I could extend it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment