31

I'm following the DRF docs to setup TokenAuthentication, and can't get it working with the browsable API. I believe I've added the proper lines in settings.py:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
    ),

INSTALLED_APPS = (
   ...
'rest_framework',
'rest_framework.authtoken',
   ...

As well as generated tokens for existing users with the code snippet from the docs. I can see tokens for each user if I query the authtoken_token table, so I know they exist.

Everytime I try to log in to the browsable API, I get the following content returned:

HTTP 401 Unauthorized
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
WWW-Authenticate: Token

{
"detail": "Authentication credentials were not provided."
}

So it appears to be attempting Token authentication, but this message is a little odd. When I enter an incorrect password, I get the 'enter a correct password' message on the login form. When I enter the correct password, it appears to login, but takes me to the API root with the above message, and displays "Log In" on the top menu, rather than the username.

Could this be related to my custom user model somehow? Or could it be due to the fact that I'm currently developing with the dev server, which doesn't support https- the DRF docs mention needing HTTPS with TokenAuthentication, though I wasn't sure if that was a best practice or actually required.

3 Answers 3

37

You can't use the browsable api with TokenAuthentication. You have to add SessionAuthtication to your settings (http://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication):

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
    'rest_framework.authentication.SessionAuthentication',
),
Sign up to request clarification or add additional context in comments.

5 Comments

If I add this auth, it does not mean that anyone who make request to my server will access just with username and password (as without token auth), does it? It just works for websites I guess, but I wanted to be sure.
Even 'rest_framework.authentication.BasicAuthentication' would serve the purpose. I prefer it because ideally SessionAuthentication should be only used when your server and client both run in same context like django templates. @KutayDemireren - yes anyone with username/password and proper permission will have access to the APIs. But its upto you to publish API endpoint or not.
For other newbies that might be confused. Basically my understanding is that the session auth allows you to actually login to the browserable API via your username and password and view the docs. I believe the token auth protects your API endpoints, and the session auth allows you to access them via browserable API. I'm not sure if exposing the session auth weakens security at all. I'll leave that to others.
works for me. Specify token above session and you can sign in on the phone app and browsable api.
To clarify here for anyone reading these comments in the future, the browser is just an HTTP client like any other. Adding SessionAuthetication in this way allows this type of authentication for all clients, not just the browseable API.
7

You can use a browser plugin to set token in the header. I'm using Modheader which is free.

The example of setting the header:

set header in modheader

I wrote a blog post on how this can be done: link to post.

I like this solution because you don't need to change the auth classes.

1 Comment

This is the best response, because it does not require you to change your authentication scheme to use the browsable API. Thrilled to use this.
1

I did:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
    'rest_framework.authentication.SessionAuthentication',
),

and I added a custom auth class in api.py

class CustomAuthToken(ObtainAuthToken):

    authentication_classes = [TokenAuthentication]

    def post(self, request, *args, **kwargs):
        ...
        return Response({...})

See https://www.django-rest-framework.org/api-guide/authentication/#by-exposing-an-api-endpoint

Comments

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.