0

In a Typescript-React SPA, I'm trying to access the document.cookie in order to retrieve a token sent together with a JWT cookie, intended to protect my Flask API against CSRF attacks, as described here.

The basic idea is that my API will send 2 cookies: one containing the JWT and flagged with the Secure & HttpOnly attributes, and another one that should be readable by JS with a token that, when sent back in the request Headersto the server should match a token encrypted in the JWT and thus verify if it's a CSRF attack or not.

To grab said token, I'm using the following function:

export default function getCSRFCookie() {
    console.log(document.cookie);
    const cookiesString = `; ${document.cookie} `;
    const CSRFCookie = cookiesString.split(`; csrf_access_token=`);

    return CSRFCookie.length === 2 ? CSRFCookie.pop()?.split(';').shift() : '';
}

However, document.cookie always ends up being an empty string, even although the relevant cookie doesn't have the HttpOnly flag, which is the one that prevents JS from reading it in document.cookie:

csrf_access_token=<token_value>;
Expires=Wed, 21 Dec 2022 00:33:53 GMT;
Max-Age=7200; Secure; Path=/;
SameSite=None

The following are the relevant Flask & Flask JWT Extended configurations that set the cookies up, but personally I don't think this is a server issue, because I saw, the cookies have the correct attributes matching the settings below:

# Flask JWT Extended specific configurations:
JWT_COOKIE_CSRF_PROTECT = True
JWT_COOKIE_SECURE = True
JWT_COOKIE_SAMESITE = "None"

# Flask config values, which are explicitly set to override default values.
# See https://flask.palletsprojects.com/en/2.2.x/security/#security-cookie
SESSION_COOKIE_HTTPONLY = False
SESSION_COOKIE_SAMESITE = "None"

The Flask application is already deployed in Linode, has got its own domain as well as an SSL certificate. I believe this is a front end problem.

I've tried to:

  • Access from http://127.0.0.1:3000 instead of localhost, as a comment in this answer suggests.
  • Access from both HTTPS (through HTTPS=true npm run start) and regular HTTP.
  • Check any default setting that might set the wrong attribute implicitly (such as Flask's SESSION_COOKIE_HTTPONLY, but as I wrote above, all those attributes appear to be correct and besides, the cookie I get doesn't have the HttpOnlyattribute.
  • The SameSite attribute is already set to None, as several comments and answers suggest in this question
  • Deleting all the cookies sent by my API before trying again after a change.

In order to continue working in other features, I've provisionally set the JWT_COOKIE_CSRF_PROTECT property to False, but that cannot remain that way since it's an obvious security risk.

LeperAffinity666
  • 364
  • 4
  • 14

0 Answers0