* Inability to invalidate stateless JWT tokens can be more or less be remedied with a short expiration time of the token and a token refresh flow. If a token is only valid for 5 minutes, and you can only refresh the token during that 5 minute window, it greatly reduces the attack vector. If that risk is too high, you should easily implement state with the same Redis setup that author mentions
* a classic CSRF example where youre logged into your app in one tab and you open a malicious link in another tab is not a threat if you, like the author suggests, use cookies for storage, but not for authentication. If you pass a token around in an "Authentication" header and have the server IGNORE the cookie which will inadvertently be sent, the request made in another tab via a malicious website is not going to be authenticated.
There are definite Usability and security pros to using Session cookies for storage:
* Unlike Session Storage, the cookies are visible by your application if you have two instances of it running in different tabs/windows.
* Unlike Local Storage, session cookies get wiped out when the user closes their browser