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. http://django-rest-framework.org/api-guide
However, I'm struggling with the Token Authentication part of the documentation, its a little lacking or does not go into as much depth as the tutorials.
http://django-rest-framework.org/api-guide/authentication/#tokenauthentication
It says I need to create tokens for users but does state where, in models.py?
My question is:
Can someone explain the Token Authentication part of the documentation a little better for a first timer?
On Django 1.8.2 and rest framework 3.3.2 following all of the above was not enough to enable token based authentication.
Although REST_FRAMEWORK setting is specified in django settings file, function based views required @api_view decorator:
Otherwise no token authentication is performed at all
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 yourINSTALLED_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:
(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:
Once the token is created (and saved), it will be usable for authentication.
There is a cleaner way to get the user token.
simply run manage.py shell
and then
then a record should be found in table DB_Schema.authtoken_token
In addition to the excellent answers here, I'd like to mention a better approach to token authentication: JSON Web Token Authentication. The implementation offered by http://getblimp.github.io/django-rest-framework-jwt/ is very easy to use.
The benefits are explained in more detail in this answer.
Just to add my two cents to this, if you've got a custom user manager that handles user creation (and activation), you may also perform this task like so:
If you already have users created, then you may drop down into the python shell in your terminal and create Tokens for all the users in your db.
That's all she wrote folks! Hope that helps someone.
@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):
Do the following things BEFORE you create the superuser. Otherwise, the superuser does not get his/her token created.
Go to settings.py and add the following:
Add the following code in myapp's models.py:
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
Open up a console window, navigate to your project dir, and enter the following command:
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)
create a superuser with
python manage.py createsuperuser
. Now, take a look at the authtoken_token table in your DB withselect * from authtoken_token;
, you should see a new entry has been added.Using
curl
or a much simpler alternative httpie to test access to your api, I am using httpie: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):
(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:
Using httpie to verify:
In the return body, you should see this:
That's it!