2

I am building a website with a separate Javascript frontend and a Django backend. My backend uses CSRF protection.

Now the problem is that the CSRF token is being set on the client side as a cookie on the backend's domain, e.g. api.example.com and this cookie is not accessible from the fronted frontend.example.com or somethingelse.com. The cookie has HTTPOnly set to false and is therefore accessible to scripts.

How can I access the cookie or otherwise deal with CSRF protection in a situation like this, where the frontend and the API are on different domains?

Screenshot of cookie inspector.

5
  • Insight into what? What is your question and what are you trying to accomplish?
    – schroeder
    Commented Jun 3, 2022 at 19:01
  • I want to use CSRF protection in this set up but I am unable to access the CRSF token from fronted, as the cookie is being set backend's domain.
    – atskdev
    Commented Jun 3, 2022 at 19:39
  • you should keep a single domain... if you let the front end make calls to multiple domains you are cross-site scripting. Have your server make the calls to the other APIs if that's necessary. CSRF will tie your session (which is for a single domain) to your form. (Cookie and hidden form field values are checked against each other). You should probably set all your sensitive cookies to httponly and same-site. It's just better from a security standpoint. Your scripts won't need access to those since they will be sent along with every request to the domain they have been set from. Commented Jun 3, 2022 at 21:04
  • @pcalkins that's why I want to know, if I can give CSRF token ownership to fronted domain.
    – atskdev
    Commented Jun 4, 2022 at 8:17
  • I'm not real sure what you mean by "fronted domain"... can you clarify that a bit? Commented Jun 4, 2022 at 16:18

2 Answers 2

1

Cookie-based CSRF protection (typically called the "double-submit cookie" pattern, because the same value is submitted in the request body and in a cookie) is not a great way to prevent CSRF. It's vulnerable to any attack that allows planting or manipulating the victim's cookies, and cookies have a weird security model that is looser than the same-origin policy which underlies most other web security. However, if you want to use it in this scenario anyhow, you'll simply have to send the anti-CSRF token in the response body as well as in the cookie. There are ways to do this, even cross-origin. If you're loading HTML pages directly (possibly with HTML form elements), you can embed the value in a hidden element. If you're loading page data into templates or constructing the DOM on the client, you are presumably already using CORS (or, $DEITY help you, JSONP) and can return the anti-CSRF token in the JSON (or whatever) message. You can also have an API specifically for getting the current anti-CSRF token value. All of this is compatible with preserving the statelessness of double-submit cookies; the server just returns whatever value was in the cookie it received, or generates a new value and both sets it as a cookie and returns it in the response.

If you want to go with better options, there are a few of them. Presumably you're using cookies for session tokens already (otherwise you're almost certainly already immune to CSRF); you can just make the anti-CSRF token be a hash or HMAC of the session token (assuming it doesn't change too often), rather than setting another cookie and/or requiring the client to see and parse cookies in JS. Alternatively, since you're probably already using CORS, you can just require that all state-changing requests be non-simple requests that require CORS preflights (any request that an HTML form couldn't make requires a preflight, e.g. use a verb other than GET/POST/HEAD, use a content type such as "application/json" and enforce this on the server, use any custom header even if the value is a constant) and make sure your CORS configuration doesn't allow any origins other than the trusted frontends. You could also stop using cookies for session tokens, and switch entirely to transmitting the session token in another way (almost certainly HTTP Authorization: Bearer <value> tokens, commonly called "bearer tokens"). Since those have to be manually set by the caller, they are immune to CSRF (if the attacker knows the session token, they don't need to use the victim's browser/client at all).

2
  • thanks. What do you suggest would be good authentication/authorization implementation for the API endpoint that is intended to be accessed from web, mobile as well as desktop?
    – atskdev
    Commented Jun 4, 2022 at 8:00
  • I'd need to know more to say for sure, but generally: Bearer tokens would be my advice there. Inherently secure against CSRF, and no important behavioral differences on browsers vs. other clients. The main weakness is that, in the event of XSS, the attacker could steal the token, but XSS is a huge problem anyhow as the attacker can just remote-control the session, invisibly, until the victim closes the tab or logs out, and even brief access is usually enough. There are ways to prevent use of stolen tokens (by adding HTTPonly cookies again) but they aren't worth it, IMO.
    – CBHacking
    Commented Jun 4, 2022 at 8:24
0

Have your client side code obtain CSRF token from backend domain and then send that token in a simple dummy request to frontend domain, which will set CSRF cookie just for frontend domain

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .