14

I'd like to use Django Rest Framework auth but I want to have more than one token for one user. In order to do that I need to implement my own Token model, I found this in Token authentication class:

class TokenAuthentication(BaseAuthentication):
    """
    Simple token based authentication.
    ...
    """

    model = Token
    """
    A custom token model may be used, but must have the following properties.

    * key -- The string identifying the token
    * user -- The user to which the token belongs
    """

But I don't have an idea how I can specify this model. Should I subclass TokenAuthentication?

0

2 Answers 2

17

Define you own authentication method in settings.py:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'my_project.my_app.authentication.MyOwnTokenAuthentication',
     ),
}

In authentication.py:

from rest_framework.authentication import TokenAuthentication
from my_project.my_app.models.token import MyOwnToken

class MyOwnTokenAuthentication(TokenAuthentication):
    model = MyOwnToken

In models.py:

import binascii
import os

from django.db import models
from django.utils.translation import ugettext_lazy as _
from my_project.companies.models import Company


class MyOwnToken(models.Model):
    """
    The default authorization token model.
    """
    key = models.CharField(_("Key"), max_length=40, primary_key=True)

    company = models.OneToOneField(
        Company, related_name='auth_token',
        on_delete=models.CASCADE, verbose_name="Company"
    )
    created = models.DateTimeField(_("Created"), auto_now_add=True)

    class Meta:
        verbose_name = _("Token")
        verbose_name_plural = _("Tokens")

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super(MyOwnToken, self).save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

    def __str__(self):
        return self.key
Sign up to request clarification or add additional context in comments.

3 Comments

but, how can I call "MyOwnTokenAuthentication" from view?
@RajuSingh you don't need to add anything to views, after you define DEFAULT_AUTHENTICATION_CLASSES, you're defining MyOwnTokenAuthentication as middleware function. Then, on your APIViews, you can access the authenticated user with "self.request.user" . You can also define authentication per view basis: authentication_classes = [MyOwnTokenAuthentication]
Getting 'MyOwnToken' object has no attribute 'user' when trying to use this approach. It seems to me that it still has to be connected with a user, is that correct?
9

What that message is saying is that the model Token can be swapped out with any other model, as long as it has properties key and user. That way, if, for instance, you want a more complicated way to generate token keys, you can define your own model.

So if you want a custom Token model, you should do the following:

  1. Subclass the Token model from rest_framework.authtoken.models. Add whatever custom behavior you want here, but make sure it has a key property and user property.
  2. Subclass the TokenAuthentication class from rest_framework.authentication. Set its model property to whatever your new Token model is.
  3. Make sure to reference your new authentication class in whatever views you want.

1 Comment

Hi Jamie, i'm using rest_framework.authtoken.models Token. i can see 3 fields which is key, created_at and user_id. my question is how can i add an extra field like company_id to that model? Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.