MattG
MattG

Reputation: 1932

Request current users API token Django REST Framework

I have a Django web app that is using the Django REST framework to generate various API endpoints. I can ensure only logged in users can view/read these endpoints, but now I am at the stage of development where I want users to post to the API using tokens. I have successfully done this, however, I have hard-coded the users token into the post request in Javascript... This worked for testing but obviously is not a good final solution.

Is it possible to request the current users token somehow? Could I then include this token in the POST request head automatically?

Thanks for any help/feedback in advance!!

EDIT: I think I am close, but I am getting a few errors in my chrome console, and still can't retrieve token.

Console Errors:

toggleScript.js:25 Uncaught DOMException: Failed to execute 
'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.
    at getToken (http://127.0.0.1:8000/static/defaults/toggleScript.js:25:7)
    at manageDefaults 
(http://127.0.0.1:8000/static/defaults/toggleScript.js:62:5)
    at HTMLInputElement.onclick (http://127.0.0.1:8000/defaults/:1:1)
getToken @ toggleScript.js:25
manageDefaults @ toggleScript.js:62
onclick @ (index):1
toggleScript.js:24 POST http://127.0.0.1:8000/api-token-auth/ 415 
(Unsupported Media Type)

I have a button when pressed, will trigger the function to retrieve the token, and this is what is causing the error stack above.

toggleScript.js

function getToken(){
  var xhr = new XMLHttpRequest();
  var url = 'http://127.0.0.1:8000/api-token-auth/';
  xhr.open("POST", url, true);
  var data = JSON.stringify({"username": "myusername", "password": "mypassword"});
  xhr.send(data);
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
          var json = JSON.parse(xhr.responseText);
          console.log(json.token);
      }
  };
}

Upvotes: 0

Views: 610

Answers (1)

Will Keeling
Will Keeling

Reputation: 23014

Django Rest Framework provides an API endpoint for requesting a user's token, given a username and password. You can wire the view into your urls.py:

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

Then when you POST a valid username and password to that view it will return the token in a JSON response:

{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }

Your app can then store that and send it in subsequent requests.

An example of retrieving the token using JQuery (assuming the view was mapped to the path ^auth-token/ in your urls.py):

$.post('/auth-token/', { username: 'admin', password: 'whatever' }, function(data) {
    // Token available as data.token
});

If you try and post to the auth-token view from within an already authenticated session, Django will likely reject the request with a CSRF token missing or incorrect response. You should either ensure that the session is not authenticated when you retrieve the token, or you could potentially include the X-CSRFToken header in the request. You'd need to extract the value from the csrftoken cookie. For example (using JQuery and the JQuery Cookie plugin):

$.ajax({
    url: "/auth-token/",
    type: "POST",
    headers: { 
        "X-CSRFToken": $.cookie("csrftoken")  # Extract the csrftoken from the cookie
    },
    data:{ username: "admin", password: "whatever" },
    dataType:"json"
}).done(function(data) {
    // Token available as data.token
});

More info on obtaining an auth token here

Upvotes: 1

Related Questions