Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework Token Authentication

I have read the Django Rest Framework Guides and done all the tutorials. Everything seemed to make sense and work just how it should. I got basic and session authentication working as described.

django rest framework - api guide

However, I'm struggling with the Token Authentication part of the documentation, it's a little lacking or does not go into as much depth as the tutorials.

django-rest-framework - token authentication

It says I need to create tokens for users but does state where in models.py?

Can someone explain the Token Authentication part of the documentation a little better for a first-timer?

like image 758
Prometheus Avatar asked Feb 12 '13 17:02

Prometheus


People also ask

How do I get authentication token in Django Rest Framework?

This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. Make sure to run manage.py migrate after changing your settings. The rest_framework.authtoken app provides Django database migrations.

Which authentication is best in Django Rest Framework?

Django-Knox is a framework that makes the authentication of the API endpoints built with the Django Rest Framework easier. However, Knox is also a token-based authentication like JSON Web Token (JWT) auth. Django-Knox comes with well-detailed documentation for easy implementation.

How do I use authentication token in REST API?

Users of the REST API can authenticate by providing a user ID and password to the REST API login resource with the HTTP POST method. An LTPA token is generated that enables the user to authenticate future requests. This LTPA token has the prefix LtpaToken2 .


2 Answers

@ian-clelland has already provided the correct answer. There are just a few tiny pieces that wasn't mentioned in his post, so I am going to document the full procedures (I am using Django 1.8.5 and DRF 3.2.4):

  1. Do the following things BEFORE you create the superuser. Otherwise, the superuser does not get his/her token created.

  2. Go to settings.py and add the following:

    INSTALLED_APPS = (     'rest_framework',     'rest_framework.authtoken',     'myapp', )  REST_FRAMEWORK = {     'DEFAULT_PERMISSION_CLASSES': (         'rest_framework.permissions.IsAuthenticated',     ),     'DEFAULT_AUTHENTICATION_CLASSES': (         'rest_framework.authentication.TokenAuthentication',     ) } 
  3. Add the following code in myapp's models.py:

    from django.db.models.signals import post_save from django.dispatch import receiver from rest_framework.authtoken.models import Token from django.conf import settings  # This code is triggered whenever a new user has been created and saved to the database @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs):     if created:         Token.objects.create(user=instance) 

    Alternatively, if you want to be more explicit, create a file named signals.py under myapp project. Put the code above in it, then in __init__.py, write import signals

  4. Open up a console window, navigate to your project dir, and enter the following command:

    python manage.py migrate python manage.py makemigrations 

    Take a look in your database, a table named authtoken_token should be created with the following fields: key (this is the token value), created (the datetime it was created), user_id (a foreign key that references the auth_user table's id column)

  5. create a superuser with python manage.py createsuperuser. Now, take a look at the authtoken_token table in your DB with select * from authtoken_token;, you should see a new entry has been added.

  6. Using curl or a much simpler alternative httpie to test access to your api, I am using httpie:

    http GET 127.0.0.1:8000/whatever 'Authorization: Token your_token_value' 

    That's it. From now on, for any API access, you need to include the following value in the HTTP header (pay attention to the whitespaces):

    Authorization: Token your_token_value 
  7. (Optional) DRF also provides the ability to return a user's token if you supply the username and password. All you have to do is to include the following in urls.py:

    from rest_framework.authtoken import views  urlpatterns = [     ...     url(r'^api-token-auth/', views.obtain_auth_token), ] 

    Using httpie to verify:

    http POST 127.0.0.1:8000/api-token-auth/ username='admin' password='whatever' 

    In the return body, you should see this:

    {     "token": "blah_blah_blah" } 

That's it!

like image 179
Cheng Avatar answered Sep 23 '22 05:09

Cheng


No, not in your models.py -- on the models side of things, all you need to do is include the appropriate app (rest_framework.authtoken) in your INSTALLED_APPS. That will provide a Token model which is foreign-keyed to User.

What you need to do is decide when and how those token objects should be created. In your app, does every user automatically get a token? Or only certain authorized users? Or only when they specifically request one?

If every user should always have a token, there is a snippet of code on the page you linked to that shows you how to set up a signal to create them automatically:

@receiver(post_save, sender=User) def create_auth_token(sender, instance=None, created=False, **kwargs):     if created:         Token.objects.create(user=instance) 

(put this in a models.py file, anywhere, and it will be registered when a Django thread starts up)

If tokens should only be created at certain times, then in your view code, you need to create and save the token at the appropriate time:

# View Pseudocode from rest_framework.authtoken.models import Token  def token_request(request):     if user_requested_token() and token_request_is_warranted():         new_token = Token.objects.create(user=request.user) 

Once the token is created (and saved), it will be usable for authentication.

like image 27
Ian Clelland Avatar answered Sep 26 '22 05:09

Ian Clelland