I'm using Flask-JWT-Extended and double submit cookie method from there for my Flask backend and React Frontend. So when user logs in from frontend, backend sets total of 4 different cookeis: csrf_access_token
, csrf_refresh_token
, access_token_cookie
, refresh_token_cookie
. Out of these 4 cookies, access_token_cookie
and refresh_token_cookie
should be HTTPonly
cookie, and thus not accessible by JS and csrf_access_token
and csrf_refresh_token
are non-HTTPonly
cookie. So the idea here is that HTTPOnly
cookie holds user's session information with CSRF token and non-HTTPonly
cookie holds the CSRF token and when POST request is made, CSRF token accessed by JS is sent to backend along with the other cookies.
This was working just fine in my development environment, two of the cookies were accessible by JavaScript and thus I could send csrf_acccess_token
along with the request with withCredentials
True, but when I deploy this to test environment with TLS using Nginx (Both backend and frontend), it is setting all 4 cookies as HTTPOnly
cookie, and thus, I cannot make any POST request.
I'm not sure whether this was caused by the Nginx
, but from what I can tell, I don't see much options to turn off 2 of the HTTPOnly
cookies being registered from the backend.
Below is my configuration for flask-jwt-extended
CORS_HEADERS = "Content-Type,X-CSRF-TOKEN"
JWT_TOKEN_LOCATION = ["cookies"]
JWT_COOKIE_SECURE = True
#JWT_COOKIE_SAMESITE = None
JWT_ACCESS_TOKEN_EXPIRES = 600
JWT_REFRESH_TOKEN_EXPIRES = 1200
JWT_CSRF_IN_COOKIES = True
JWT_COOKIE_DOMAIN = ".mydomain.com"
#JWT_ACCESS_COOKIE_PATH = '/'
#JWT_REFRESH_COOKIE_PATH = '/'
JWT_COOKIE_CSRF_PROTECT = True
JWT_SECRET_KEY = "secret"
Any advice would be greatly appreciated!
Flask-JWT-Extended should never be setting the csrf cookies as httponly. I wonder if there is an nginx setting that is converting all cookies to httponly (something like proxy_cookie_path)?
If that’s the case, another approach you could take it to set JWT_CSRF_IN_COOKIES
to false, and use https://flask-jwt-extended.readthedocs.io/en/stable/api/#flask_jwt_extended.get_csrf_token to grab the csrf token when a JWT is created, return it as part of the JSON payload, and store it in localStorage instead of in those non-httponly cookies so that your JavaScript can still grab it when making requests.