2

I've spent six hours on it and I still can't handle getting CSRF Token and Session ID.

I have these two simple functions:

@api_view(["GET"])
@ensure_csrf_cookie
def getCsrf(request):
    return Response({'success': get_token(request)})

@method_decorator(csrf_exempt, name='post')
class LoginView(views.APIView):

    permission_classes = (AllowAny,)

    def post(self, request, format=None):
        serializer = LoginSerializer(data=self.request.data, context={ 'request': self.request })
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return Response(None, status=status.HTTP_202_ACCEPTED)

I have corsheaders installed and I have these settings:

CORS_ALLOWED_ORIGINS = [
    'http://127.0.0.1:3000',
    'http://localhost:3000',
    'http://127.0.0.1:8000',
    'http://localhost:8000',
]

CSRF_TRUSTED_ORIGINS = [
    'http://127.0.0.1:3000', 
    'http://localhost:3000',
    'http://127.0.0.1:8000', 
    'http://localhost:8000',
]

CORS_ALLOW_HEADERS = ('Access-Control-Allow-Origin', 'Access-Control-Allow-Credentials', 'Authorization', 'Content-Type', 'Cache-Control', 'X-Requested-With', 'x-csrftoken')
CORS_ALLOW_CREDENTIALS = True

CSRF_COOKIE_HTTPONLY = False
SESSION_COOKIE_HTTPONLY = False
CSRF_USE_SESSIONS = False

CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
SESSION_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SAMESITE = 'None'

So, both of those cookies appear in the responses. Neither of them are written in the browser. I've tried everythong I found. This is my React part

axios.defaults.withCredentials = true;

useEffect(() => {
    axios.get(`http://127.0.0.1:8000/csrf/`)
        .then(response => {
            Cookies.set('csrftoken', response['data']['csrf']);
        })
        .catch(error => {
            console.log(error);
        });
}, []);

function onSubmit(e) {
    e.preventDefault();

    let data = {
        username: e.target.username.value,
        password: e.target.password.value
    };

    const config = {     
        headers: { 
            'content-type': 'application/json',
            'Access-Control-Allow-Credentials': 'true',
            'Access-Control-Allow-Origin': 'http://localhost:8000',
            'X-CSRFToken': Cookies.get('csrftoken')
        },
        withCredentials: true,
        crossDomain: true
    }

    axios.post(`http://127.0.0.1:8000/login/`, JSON.stringify(data), config)
        .then(response => {
            console.log(response);
        })
        .catch(error => {
            console.log(error);
        });
}

I'd like not to set cookies by myself as it is now in useEffect, but I can't make it work. I don't know how to get session id, I want it to work as it supposed. I've tried Chrome and Firefox. None of them save those cookies.

Lothric
  • 1,283
  • 2
  • 6
  • 11
  • Why do you have this `Cookies.set('csrftoken', response['data']['csrf'])`? You are trying to read the csrf token from the body response. This is a cookie, so it is not sent in the body. Seem that all the configurations are correct, so what it is the response status code to the request 'http://127.0.0.1:8000/csrf/'? – Jony_23 Jun 24 '22 at 16:25
  • @Jony_23 I know that I shouldn't set it like that, I wrote that in my question. I made csrf token to be returned in the response body. They are just not being set in the browser. I think it's just some kind of implossible thing. At first CORS policies which restricts everything so you can't do anything at the development stage since you can't set https connection. And then it still doesn't work. Maybe I am missing something here but I surrendered to that and I've made JWT Auth. I should've done that from the beginning to save the time. – Lothric Jun 24 '22 at 16:36
  • @Jony_23 responses were good, I've seen both of CSRF token and Session id in Set-Cookie header. And they weren't http-only – Lothric Jun 24 '22 at 16:37
  • Maybe just adding: `axios.get(`http://127.0.0.1:8000/csrf/`, {withCredentials: true})` to the axios request work. You should try to set CSRF_COOKIE_DOMAIN and (if you are using linux) edit /etc/host/ to set the domain in both; and figure out if you cookie is set. – Jony_23 Jun 24 '22 at 16:42
  • It's easy to run django over https. Check these: [How can I test https connections with Django as easily as I can non-https connections using 'runserver'?](https://stackoverflow.com/questions/8023126/how-can-i-test-https-connections-with-django-as-easily-as-i-can-non-https-connec), [How to run a local Django development server over HTTPS with a trusted self-signed SSL certificate](https://timonweb.com/django/https-django-development-server-ssl-certificate/) It's not impossible get the csrf. I have done it. – Jony_23 Jun 24 '22 at 16:48

1 Answers1

0
const get_cookie = (name) => {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
  };

// then
get_cookie('csrftoken')
rjhcnf
  • 762
  • 6
  • 12