I\'m really stuck. Here\'s what I\'m trying to do.
First of all you want to use SessionAuthentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
)
}
This will enforce CSRF, except for anonymous users (more on this in a bit). For browser frontends the easiest solution is to have both the (browser) frontend and backend under the same domain - this lets you avoid CORS - as suggested by comments above. If you have other clients then just go with tokens (DRF tokens or JWT) - but these are not safe for browser usage due to the danger of XSS attacks (storing tokens in localStorage is inherently insecure).
As you are using axios, CSRF setup is dead easy:
import axios from 'axios'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
axios.defaults.xsrfCookieName = 'csrftoken'
So you should have safe sessions with CSRF enforced. Almost. To quote the linked page above:
Warning: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.
CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.
This is icky - you either have to just use Django server-side views which makes your SPA design somewhat more complicated or recreate login and other auth views in DRF, with the caveat of using the @csrf_protect method decorator to enforce CSRF on these "anonymous" views. Obviously such views will break for token-using clients so you probably want to use different endpoints for these (maybe re-using the same base classes). So your browser login uses /auth/browser/login/ and your mobile login /auth/mobile/login/, the former wrapped using @csrf_protect.
Recreating login and other auth views from scratch should be done carefully after studying the contrib auth source code; for vanilla requirements I would recommend pre-existing solutions like django-rest-auth and django-all-auth. The django-rest-auth package however is not well designed for browser frontends and forces the usage of token generation, plus you would need to wrap the views as described above. On the other hand, all-auth provides AJAX responses for JS clients and might be a better bet.