When storing JWTs in HttpOnly cookies, you're protecting the token from JavaScript-based XSS (Cross-Site Scripting) attacks, as these cookies cannot be accessed or manipulated by client-side scripts. However, this alone does not prevent CSRF (Cross-Site Request Forgery) attacks, where a malicious website might automatically include the JWT cookie in a request to your server, potentially leading to unwanted actions.
To defend against CSRF attacks, you need to implement a CSRF token. The CSRF token is usually stored in a non-HttpOnly cookie or as part of the HTML response. This token is then manually sent with requests, often in a custom HTTP header (e.g., X-CSRF-Token). When a request is made, the server validates that the CSRF token matches what was set for that session. Since an attacker’s site won’t have access to this token, they cannot forge legitimate requests.
In this way, the HttpOnly cookie protects the JWT from XSS, while the CSRF token ensures requests are coming from legitimate sources, offering comprehensive protection.
For further reading on the topic, consider reviewing the following resource: