Search code examples
securitywebjwtsingle-page-applicationcsrf

Single Page Applications and CSRF


Let us say we have an SPA being served by nginx at domain example.com and a REST API hosted at api.example.com.

Authentication between the SPA and the API happens through a JWTs. A short lived (15 min) access-token that is stored by the SPA in localstorage and a longer lived (days) refresh-token that is set by the server on an HttpOnly cookie. CORS is permitted on the server for the domain example.com.

Problem 1: I was discussing this yesterday with a colleague and they believe that because my refresh token resides in a cookie, I require CSRF protection for my application. I disagreed on the account that the refresh-token can not be used to "access" any private resource and is only checked for by the server during a GET request to a specific end-point which exposes the token exchange mechanism to the SPA.

Q1. Is this reasoning correct? Is there any way that a refresh-token in an HttpOnly cookie be exploited maliciously?

Problem 2: Thinking further on the subject, even if we were to go for some CSRF protection, if for nothing then peace-of-mind. How would you go about sending the token to the client in the first place? We do not use forms and render the UI completely on the client so a hidden field is out of the question, the index file is served by nginx so we can not embed a meta tag on the HTML either.

Q2. Is there any way to make CSRF protection work for a Single Page Application?


Solution

  • I believe holding the refresh token in a cookie is ok. Just make sure the cookie may be sent only to the one endpoint responsible for the refresh and fulfill other cookie protection requirements as mentioned in V3.4 of the OWASP Application Security Verification Standard available here.

    What is the worst thing that may happen if someone attacks you over CSRF then? He may force you to refresh the token. But the token will not be exposed by any means to the attacker, so no leakage will take place.

    If despite this you will be forced to tackle the CSRF problem, have a look at this too: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html