— Not if you issue new tokens for every request
If you issue tokens for every request with a refresh token, like with OAuth, and still use a SPA/webapi, it doesn't matter as an attacker can then abuse that refresh token, and it does not help whatsoever
— You basically have to get rid of all XSS vulnerabilities to make it hardened, put jwt in HTTPOnly, SSL-only cookie that no client script can access, then refresh token in localstorage
— It's totally at odds with all anti CSRF knowledge out there, and hard to implement securely unless you have revocation
— I similarly used to deploy jwt in SPA/webapi apps and found the same, wrote my own jwt library, and spent a year researching how to secure it... without a blacklist table there is no way to secure it in a way that would let me sleep at night personally
— Otherwise, even if your app is aware of CSRF, it can't stop it
— So the right way is?
— 10 Best Practices for Writing Node.js REST APIs | RisingStack
— In order for an attacker to see session data, they would need to be able to send both the CSRF token and cookie, one of which they can't read, and the other they can't get if there are no XSS holes
— You can store a hashed CSRF token in localstorage and keep the unhashed one in the JWT.
— Set cookie, check cookie