I'm the author of https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
When XSS exist on a page, an attacker is privileged to:
- HTML5 web storage (local and session)
- Cookies that are not set with httpOnly flag
- Control of the tab until it is closed and the ability to make unauthorized requests
You can also start to formulate attacks to get around XSRF protection.
When an XSRF vulnerability exists, an attacker is privileged to:
- Making unauthorized requests from a 3rd party domain, if you can lure a user there (or send them there in the presence of XSS).
You can see that when an XSS vulnerability exists, you are able to make unauthorized requests and an attacker would need to jump through some more hoops to exploit XSRF. This means that when XSS exists (regardless of XSRF protection or not), the attack vector of making unauthorized requests will exist.
Hopefully, that clears things up for my next point.
An XSRF attacks or unauthorized requests has less impact and scope than stealing a stateless token that represents the user's identity and session. Leaking the token means that an attacker will have full control to formulate an attack on behalf of the user, on his time, on his machines.
In conclusion, in presence of XSS when you:
store an access token in web storage, the tokens for any user that uses your site during the time of the existence of XSS is compromised. This means an attacker could get thousands of valid access tokens and can possibly do a lot of harm (even more if you store refresh tokens in web storage). The users are also vulnerable to making unauthorized requests from their own browser.
store an access token in a httpOnly cookie, the tokens for any user are not compromised. But, the users are also vulnerable to making unauthorized requests from their own browser even in the presence of XSRF protection.
Hope this information helps.