Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django + DRF: 403 FORBIDDEN: CSRF token missing or incorrect

I have an Android client app that tries to authenticate with a Django + DRF backend. However, when I try to login, I get the following response:

403: CSRF Failed: CSRF token missing or incorrect.

The request is sent to http://localhost/rest-auth/google/ with the following body:

access_token: <the OAuth token from Google>

What could cause this? The client doesn't have a CSRF token since the POST to authenticate is the first thing to happen between the client and the server. I checked out a lot of the past questions with the same problem, but I couldn't find any solutions.

The relevant settings on the Django side are like this:

AUTHENTICATION_BACKENDS = (
    "django.contrib.auth.backends.ModelBackend",
    "allauth.account.auth_backends.AuthenticationBackend"
)

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.request",
    "django.contrib.auth.context_processors.auth",
    "allauth.account.context_processors.account",
    "allauth.socialaccount.context_processors.socialaccount"
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
    'allauth.socialaccount.providers.google',

    'django.contrib.admin',

    # REST framework
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'rest_auth.registration',
)

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ( 
        'rest_framework.permissions.IsAuthenticated'
    ),
}
like image 657
manabreak Avatar asked Sep 16 '15 07:09

manabreak


2 Answers

Why are you getting this error?

As you have not defined the AUTHENTICATION_CLASSES in your settings, DRF uses the following default authentication classes.

'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication'
)

Now, SessionAuthentication enforces the use of CSRF Token. If you don't pass a valid CSRF token, then 403 error is raised.

If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such asPUT, PATCH, POST or DELETE requests.

What you need to do then?

Since you are using TokenAuthentication, you need to explicitly define it in the AUTHENTICATION_CLASSES in your DRF settings. This should resolve your CSRF token issue.

like image 72
Rahul Gupta Avatar answered Sep 20 '22 01:09

Rahul Gupta


Silly me, I missed the TokenAuthentication framework from the REST settings:

settings.py

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

Now it works just as intended.

like image 36
manabreak Avatar answered Sep 18 '22 01:09

manabreak