I am using session authentication in my Django - React application. But no session cookie is stored in the cookie storage. (A csrf token cookie is stored!)
I cleared the local storage / session storage and the cookies I tried with different browsers
On the frontend Part, I make a post request for the login:
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.withCredentials = true;
const client = axios.create({
baseURL: "http://127.0.0.1:8000",
});
function submitLogin(e) {
e.preventDefault();
setIsLoading(true);
client
.post("/login", {
email: email,
password: password,
})
.then(function (res) {
setCurrentUser(true);
window.location.reload(); // Refresh the page after login
})
.catch(function (error) {
setIsLoading(false);
});
}
I get a status code 200, user is logged in everything seems to work fine. (When opening the application in a incognito window the log in is not working!)
Also I get a SameSite attribute error in dev tools:
Indicate whether to send a cookie in a cross-site request by specifying its SameSite attribute
even though I set everything in settings.py:
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SECURE = False # Set it to False during development with HTTP
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None' # If using cross-site requests
SESSION_COOKIE_SECURE = True # If using HTTPS
note that when setting
SESSION_COOKIE_SAMESITE = 'lax' or 'strict'
and removing
SESSION_COOKIE_SECURE = True # If using HTTPS
the log in no longer works
I also tried without setting the SESSION_ENGINE and using the default but that makes no difference (the login works but no cookie)
On the backend site I use a custom User model This is my UserLogin View:
class UserLogin(APIView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (SessionAuthentication,)
def post(self, request):
data = request.data
assert validate_email(data)
assert validate_password(data)
serializer = UserLoginSerializer(data=data)
if serializer.is_valid(raise_exception=True):
user = serializer.check_user(data)
login(request, user)
return Response(serializer.data, status=status.HTTP_200_OK)
I included corsheaders in the INSTALLED_APPS and in the MIDDLEWARE right at the top I put
"corsheaders.middleware.CorsMiddleware",
also I added:
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
All other requests from frontend to backend work fine!
I am also pretty sure rest framework is configured correctly I included rest_framework in the INSTALLED_APPS and:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
}
Why is no session cookie stored?
When you use SessionAuthentication, by default django requires 2 things
If these do not match, then an error is raised, so, there is the documentation to make it authenticate in the correct way.
When you are using SessionAuthentication, you are using Django's authentication which usually requires CSRF to be checked. So you must pass the CSRF token in the X-CSRFToken header.
This documentation provides more information on retrieving the CSRF token and sending it in requests. The CSRF token is saved as a cookie called csrftoken that you can retrieve from a HTTP response.
If you cannot retrieve the CSRF cookie, this is usually a sign that you should not be using SessionAuthentication (use TokenAuthentication or OAuth 2.0 instead).