109

Context: Angular site is hosted on S3 behind CloudFront, separate from Express server that is used as API and almost all requests are XMLHttpRequests. All requests are sent without cookies (withCredentials = false by default) and I use JWT Bearer token for authentication by taking it from cookies in angular and placing to Authorization header (This technique is kind of what is described in CSRF Wiki page).

On Express site I do not allow Cookie header in Access-Control-Allow-Headers.

Cookies have secure: true flag, and are NOT httpOnly because I need to manually access them in angular.

Also I've read in this Medium article that JSON-Web-Tokens(JWT )/Bearer Tokens

is without a doubt one of the best methods of preventing CSRF

Question 1: Will I add extra security if I'll add X-XSRF-Token header to each request and for example make the mechanism stateless by checking for that same value in JWT payload? (I'we read about it in this thread)

Question 2: Do I actually need extra security efforts agains CSRF taking all that I described?

Igor Pomogai
  • 1,193
  • 2
  • 8
  • 7

4 Answers4

102

This is relevant but doesn't necessarily answer 100% of your question:

https://security.stackexchange.com/a/166798/149676

The short of it is that as long as authentication isn't automatic (typically provided by the browser) then you don't have to worry about CSRF protection. If your application is attaching the credentials via an Authorization header then the browser can't automatically authenticate the requests, and CSRF isn't possible. Therefore, I would re-word the quote from your article slightly: it isn't that Bearer Tokens are the best defense against CSRF attacks, but simply that CSRF is an attack vector that specifically attacks requests where the browser automatically provides authentication (typically cookies and basic authentication), and so CSRF doesn't matter if the browser can't authenticate you.

You should probably make sure and verify, server-side, that your application isn't silently falling back to cookie validation if the Bearer token is absent. I could see something like that squeaking into an application by accident, and since the cookies will get sent along whether you want them to or not, it could result in an inadvertent CSRF vulnerability on a page that is was "supposed" to be immune to CSRF.

As a result, I think both your questions one and two can be answered the same way. If you only use authentication via Bearer tokens and not via cookies, then there is no concern of CSRF vulnerability, and no extra steps are required for security.

StanOverflow
  • 109
  • 2
Conor Mancone
  • 29,899
  • 13
  • 91
  • 96
  • 2
    It's Incorrect to say that "as long as authentication happens in the header and not by cookies that you don't have to worry about csrf-protection." Basic auth happens by headers and *is* vulnerable to csrf. Similarly, digest authentication, ntlm, negotiate and certificate auth can all be vulnerable to crsf. CSRF must be mitigated whenever the browser automatically sends the authentication, because then a malicious third-party can simply issue a request to the server from the user's browser and the browser will automatically send the credentials so the server can't distinguish without "help". – Nathan Jan 06 '19 at 18:48
  • 4
    @Nathan The answer I linked to mentioned exactly your point and some of those exceptions (in fact I mentioned Basic authentication as an exception in my answer). I didn't mean to imply "header auth = secure" but rather "if you are setting headers to provide auth then you are secure". Yes, there are some header-based authentication systems that a browser (or authentication server) will automatically provide, and then you have to worry about CSRF. – Conor Mancone Jan 06 '19 at 19:01
  • So If I put the JWT in cookie for future use but when sending the request, I take it from cookie and put in custom header, and at server side I am checking using only that custom header, so I am safe to both XSS and CSRF attack right? – mss Feb 19 '21 at 12:15
  • 1
    @mss That would protect you against CSRF. It would not protect you against XSS (not that anything fully can) because in order to get it out of the cookie to attach it to the custom header, you would have to disable the `httpOnly` flag. This means that an attacker could grab it during an XSS attack – Conor Mancone Feb 19 '21 at 18:01
  • @ConorMancone Thanks for clarifying, It was really helpful :>. regarding XSS, I see you point, so will doing an encryption based on some algorithm will help? .i.e whenever I store JWT in cookie I store it some encrypted format(using front-end JS code) making it an invalid JWT and when I take it out to memory from cookie, I decrypt it to the valid JWT, will that mitigate XSS to a large extent(as you mentioned, nothing can fully) – mss Feb 20 '21 at 09:20
  • 2
    @mss encrypting the cookie contents won't get you very far because the directions on how to deencrypt it are built into the program for an attacker to read to. It may slow someone down a little bit, but not really. Nothing is ever perfect, so the trick is to find a balance that works well for you. That might mean just leaving off the `httpOnly` flag, or it may mean leaving it on but using a separate cookie for your CSRF check. For reference, you're basically talking about the double submit cookie CSRF protection scheme. – Conor Mancone Feb 20 '21 at 11:45
40

Generally, CSRF happens when a browser automatically adds headers (i.e: Session ID within a Cookie), and then made the session authenticated. Bearer tokens, or other HTTP header based tokens that need to be added manually, would prevent you from CSRF.

Of course, but sort of off-topic, if you have a XSS vulnerability, an attacker could still access these tokens, but then it doesn't become a CSRF bug.

ndrix
  • 3,206
  • 13
  • 17
22

Previous answers are rock solid. I'll jump in here to provide a more context and little caveat. There are lots of ways to using JWT; session management is one of them. Although it presents a few drawbacks when dealing with timeouts and advanced requirements like re-authentication.

Also, I've seen JWT placed in Cookies. As other's have stated, CSRF protection doesn't come from using a JWT itself. It comes from submitting it as an Authorization header, using the Bearer [JWT] scheme.

Question 1: Will I add extra security if I'll add X-XSRF-Token header to each request and for example make the mechanism stateless by checking for that same value in JWT payload? (I've read about it in this thread)

If you are submitting it via XHR as an Authorization header, then no the extra X-XSRF-Token header will not add "extra" security.

Question 2: Do I need extra security efforts against CSRF taking all that I described?

Nope, your current setup is okay.

A while back, I compiled a web authentication techniques guide and their security properties (it also has a JWT part). Here is the final cheat sheet describing all methods in a compact form.

Daniel Szpisjak
  • 1,825
  • 10
  • 19
3

I feel that it's important to highlight something regarding Single Page Applications (or requests from any frontend in general) that may make CSRF protections useless. I thought at first it may be a bit off-topic here, but I'm reconsidering (see my note at the bottom).

My point: maybe you have some frontend application code that automatically makes a request to an API upon loading the app from a URL (one of the most common example is validating an email address). In this case, whether you have CSRF or not is completely irrelevant. As soon as something happens on your frontend app without requiring a specific user action, then CRSF protection is irrelevant because an attacker has a "legit" way to perform some action by simply making you open your frontend app.

Some examples that come to my mind of actions that may be performed automatically on the frontend side

  • Authentication (generating access tokens, etc)
  • Validating an email
  • Following an email link to automatically rate some content
  • (un)subscribing from emails/newsletters
  • downloading a file (if the frontend app preprocesses some stuff before forwarding the download request to the server)
  • Joining a project, a group
  • Validating a referrer code

Some of those use cases (like validating an email) may not require authentication and be relatively harmless, but some other (like joining a group) only make sense when you are authenticated, which means you have some way to automatically perform an authenticated request against an API. It's maybe less dangerous if the user has some direct feedback on what happened (assuming your frontend does give your feedback to your users), and if they can undo those operations, but it remains an attack vector.

We often think of "CSRF" as a way to protect against requests sent directly to a server app or an API. Correct me if I'm wrong, but the definition seems to encompass any attack where the malicious person is not able to see the result of what happened including using frontend app code.