Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Setting xsrfHeader for cross-domain requests has no effect on requests (the header is missing) #5122

Closed
evdoks opened this issue Nov 25, 2013 · 23 comments

Comments

@evdoks
Copy link

evdoks commented Nov 25, 2013

Configuring the httpProvider with

  $httpProvider.defaults.xsrfCookieName = 'csrftoken';
  $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

does not set X-CSRFToken header for cross-domain requests, while the requests to original domains are fine.

The Access-Control-Allow-... headers are set to allow CORS with cookies and X-CSRFToken header:

Access-Control-Allow-Headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken 
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin: origin_url
Access-Control-Allow-Credentials:true
@petebacondarwin
Copy link
Member

Can you provide a running example of this?

@petebacondarwin
Copy link
Member

This is specifically precluded: https://github.com/angular/angular.js/blob/master/src/ng/http.js#L675

@evdoks
Copy link
Author

evdoks commented Nov 25, 2013

This is something I have expected.
However, in case the backend and the angular app are running on different domains/subdomains/ports such behaviour might be required. I am still able to make the calls by using $http.defaults.headers.common["X-CSRFToken"]=$cookies['csrftoken']; before each call, though it would be much nicer to be able to set it via $httpProvider.

@petebacondarwin
Copy link
Member

Here is the commit : fce100a

@petebacondarwin
Copy link
Member

Can I ask why you need XSRF protection if you are using (and if full control of) CORS?

@petebacondarwin
Copy link
Member

Apparently before this was restricted, adding the header causes a whole load of headaches with preflight requests.

@evdoks
Copy link
Author

evdoks commented Nov 25, 2013

I ran into this issue while building an app that was talking to a Python Django Backend that was requiring XSRF protection in form X-CSRFToken header (that is typical for Django apps). The CORS was due to the backend running on a different port.

@kanzure
Copy link

kanzure commented Jan 30, 2014

@petebacondarwin, regarding "Can I ask why you need XSRF protection if you are using (and if full control of) CORS", see http://stackoverflow.com/questions/19793695/does-a-proper-cors-setup-prevent-xsrf

Also see http://www.w3.org/TR/cors/ which claims that CSRF/XSRF tokens are still required.

@Rodeoclash
Copy link

Given that we should be sending CSRF tokens cross domain, is it possible to get this reinstated?

@ondrowan
Copy link

@petebacondarwin What exactly was the problem with preflight requests?

@IgorMinar
Copy link
Contributor

Can someone please explain how CSRF for CORS services works? I have a hard time putting the dots together.

CSRF relies on cookie based authentication and on the fact that the browser adds the cookies to requests for that particular domain automatically regardless of how the request was triggered.

CORS services almost never use cookies because they don't work well for CORS. Instead http authentication or various kinds of tokes sent via http headers or url params are used. These are never added automatically to the api requests by the browser.

If anyone can please point out what I'm missing, I'd be grateful.

@ondrowan
Copy link

Eg. I use example.com for frontend and api.example.com as API to which I authenticate via session cookies that are shared between both (.example.com). I was able to set sharing of both session and CSRF token in Django backend, the only thing that's breaking it is, unfortunatelly, Angular. I thought this was pretty common scenario, but I'm new to all of this and might be missing something obvious.

@j0hnsmith
Copy link

@ondrowan I was trying to do similar but it didn't work. IIRC browsers won't set a .example.com cookie that comes from a api.example.com XHR request, if the requests were normal http requests this would be fine. I dug into angular to try to access the the header, I got down to the the raw js XHR object but the browser wouldn't give me access to the header that I could see being returned by the server.

@kanzure
Copy link

kanzure commented Feb 26, 2014

Well, suppose you have api.example.com return your CSRF/XSRF token not as a cookie, then you could imagine a way to set the AngularJS xsrfHeader value to that token for future requests against api.example.com. I don't believe that api.example.com needs to return the CSRF token as a cookie (that's obviously going to break if you are using httpOnly and for other reasons).

@j0hnsmith
Copy link

CSRF is only possible because browsers always send any available cookies with every request, regardless of whether a request originated from the expected site or a malicious site. The server determines who the request is from (and trusts that user) based on the session cookie.

Once your requests are cross origin (thus there's no session cookie) I'm not convinced that CSRF is a factor because every request from the client should have another way for the server to identify which user the request is from (eg custom header with token etc etc). The method of adding the custom header to the request will not be done automatically for every request by the browser. That doesn't mean that requests can't be forged, it just means that your browser isn't going to automatically make malicious requests look genuine.

Can anyone come up with a scenario where a cross origin request would need CSRF protection?

That said, if a developer is telling angular to set a header, I can't think of a good reason why angular shouldn't set it.

@IgorMinar
Copy link
Contributor

@ondrowan as @kanzure mentioned when doing an XHR to api.myapp.com, the browser doesn't send .myapp.com cookies (unless you use withCredentials - in which case you have to deal with CORS pre-flight).

I don't know of any serious CORS enabled api that would depend on cookie authentication. Most of them use tokens embedded in headers or even more commonly in urls (see GitHub api).

In any case, you can always set the XSRF header yourself via a interceptor if you really want that.

(Another issue to consider is that unlike with non-CORS requests, it's possible for a single app to work with several CORS enabled backends and each of them could potentially require a unique CSRF token, in cases like these, using the interceptor method I mentioned is the only sensible option).

@linclark
Copy link
Contributor

Agreed with Igor, and there hasn't been any activity in 2 months, so closing.

@joshkehn
Copy link

I'd like to see this issue reopened because I'm currently supporting cookie authentication (for an Angular frontend) to support Django's Admin as well. Currently I have CORS configured and cookie domains configured correctly but the fact that Angular refuses to send CSRF headers cross-domain is really annoying.

Is there a patch I can do per-request to re-enable this?

@pasupulaphani
Copy link

Here you find a good example to set up CSRF headers cross-domain :
http://ionicframework.com/blog/angularjs-authentication/

@zgmnkv
Copy link
Contributor

zgmnkv commented Aug 31, 2016

+1 to fix this

@petebacondarwin
Copy link
Member

@zgmnkv as pointed out by @pasupulaphani - this is configurable in the $http service via an injector: http://blog.ionic.io/angularjs-authentication/#csrf

@zgmnkv
Copy link
Contributor

zgmnkv commented Aug 31, 2016

@petebacondarwin Thanks, I know that I can implement it via interceptor or default header... But angular has csrf support out of the box, and it should just work, isn't it? It is really annoying that there is an intentional check in the code that prevents setting csrf header for cross-origin requests, I really don't understand the meaning of this piece of code.

var xsrfValue = urlIsSameOrigin(config.url)

@gkalpak
Copy link
Member

gkalpak commented Sep 6, 2016

For anyone interested, this has also been discussed in #7862 and there is a PR to make this configurable: #14890.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests