Resources that were working fine with session authentication on 3.3 are now producing a 'CSRF validation failed' error on 3.4.

Does anything need to be changed on the caller's side?

Comments

childersc’s picture

Having this exact same issue, even tried it manually with Google Chrome's Postman software. This was working fine until yesterdays update!

tyler.frankenstein’s picture

More information: https://drupal.org/node/2012982

Note that Services clients using session authentication now should supply a special X-CSRF-Token header with a token that can be retrieved from http://example.com/services/session/token. This is needed for writing HTTP methods calls (POST, PUT, DELETE).

tyler.frankenstein’s picture

Title: need Change Record for changes CSRF - 'CSRF validation failed' since update to 3.4 » getting 'CSRF validation failed' since update to 3.4
Component: Documentation » Code
Assigned: RamboLau » Unassigned
Category: task » feature
Priority: Critical » Normal
Status: Closed (fixed) » Active

Here's a new example call to the System Connect Resource in Services 7.x-3.4 using jQuery for authenticated users (anonymous users don't need the CSRF token when making a call to System Connect):

// Obtain session token.
$.ajax({
  url:"?q=services/session/token",
  type:"get",
  dataType:"text",
  error:function (jqXHR, textStatus, errorThrown) {
    alert(errorThrown);
  },
  success: function (token) {
    // Call system connect with session token.
    $.ajax({
      url: '?q=my_services_endpoint/system/connect.json',
      type: "post",
      dataType: "json",
      beforeSend: function (request) {
        request.setRequestHeader("X-CSRF-Token", token);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        alert(errorThrown);
      },
      success: function (data) {
        alert('Hello user #' + data.user.uid);
      }
    });
  }
});
childersc’s picture

Do you happen to have this in PHP?

I am a bit confused with the process, so I am going to explain it and if you wouldn't mind either providing the PHP example or confirming my process I would appreciate it.

Sorry not a huge jQuery guy lol

Step 1. Obtain the session token at "/services/session/token"
Step 2. Set a header on the next call to /rest/user/login containing the X-CSRF-Token=SessionTokenHere
Step 3. Same as step 2 but on the /rest/user/register

If I am understanding that all I have to do is obtain the session token before doing anything else, then essentially all I have to do now is update my curl scripts and provide the same session token. A confirmation would be greatly appreciated! Thank you!!

joachim’s picture

Thanks for the info!

I've filed this for Clients module #2014131: update for X-CSRF-Token in Services REST 3.4; will deal with it soon.

tyler.frankenstein’s picture

@childserc, your 1,2,3 outlined sounds correct. Any calls that use POST, PUT, or DELETE must now have a header key/value pair with "X-CSRF-Token" being the key, and the token retrieved from /services/session/token as the value to send along with the header key.

joachim’s picture

Has there been a change notice filed for this, btw?

childersc’s picture

That did not seem to work. Do I need to call /rest/system/connect before I call /rest/user/register ? it logs in just fine, the registration part is what throws this error despite that I added the new header option.

I am using POST with all of this.

ivanbueno’s picture

@childersc, here's what worked for me:
1. POST to /rest/user/login (nothing in headers). Construct the $cookie from session name + id
2. GET to /services/session/token (include $cookie in the headers). Save the $token returned.
3. Include $cookie and $token in the headers of subsequent requests of a logged in user.

childersc’s picture

@ivanbueno, Confirmed! This worked exactly how you stated that it should work :) Thank you for your assistance in debugging this issue!

RamboLau’s picture

Assigned: Unassigned » RamboLau

@ivanbueno, This is so trouble, has a better soved method?

hbochner’s picture

Thanks!

It took a couple of hours, but now my clients are upgraded, and working again.

This really should have been explained clearly in the release notes;
there are probably sites that had major failures.

In my case the failures were in a new feature that people aren't using yet, so the help
from this page came in time.

Thanks again,

joachim’s picture

Title: getting 'CSRF validation failed' since update to 3.4 » need Change Record for changes CSRF - 'CSRF validation failed' since update to 3.4
Category: feature » bug
Priority: Normal » Critical

This really needs a Change Record writing -- that's the correct way now to document something like this, and link to it or mention it in the release notes.

marcingy’s picture

Category: bug » task
ivanbueno’s picture

What do you think of making csrf restriction configurable? An ability to disable the csrf validation for a particular service. (I have resources that accept POST requests from both anon and authenticated, and csrf is not an issue.)

childersc’s picture

I agree with ivanbueno's comment. This should have had an option to enable and disable rather that instantly disabling a lot of people's scripts that never use CSRF tokens.

I too would like to this as an option!

tyler.frankenstein’s picture

I do agree the change is abrupt and has definitely broken some stuff, but it is related to a security issue (such an issue that support for Services in D6 has been dropped! :(

https://drupal.org/node/2012982

It is best to update all external code that uses your Drupal Services to pass along this new CSRF token for authenticated users using POST, PUT or DELETE methods.

I am curious though, why the new token isn't required for anonymous users in _services_sessions_authenticate_call(), or maybe I am not understanding the code. I have services that allow anonymous users to use POST methods, so shouldn't this be protected by the new token? Or does it not matter if its an anonymous user? If a Services maintainer could offer up their thoughts on this, that would be great, mmmk. Thanks!

joachim’s picture

Component: Code » Documentation
Category: task » bug

I know this is a cultural shift for a lot of maintainers, but missing documentation *is* a bug.

There may not be a problem with the code, but 3.4 is as badly broken for users as if there were.

aakkawi’s picture

try to connect with session and token, if it fails, login, collect sessionid and name in a cookie and then connect to the token resource , save the token, then include cookie and token in each request. when the client restarts again. go to the beginning of this post ... thats it. works perfect

Erich Schulz’s picture

just a clarification about #3

this technique seems to request a token before each request (effectively doubling response time)

so is it ok to cache and reuse the token?

for reference of others - this was the best reference I could find on this issue after a 5minute google:

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

Stu Phillips’s picture

this technique seems to request a token before each request (effectively doubling response time)

so is it ok to cache and reuse the token?

Yes; the token returned is specific to the session id of the users session. So the sequence quoted in #9 above is accurate.
Once logged in, acquire the token and then quote the token in subsequent requests with the same session id that require
POST, PUT or DELETE.

tyler.frankenstein’s picture

Regarding #9, will someone please explain in more detail how to create the cookie(s)? Should the cookie contain both the session id and the name, or should there be two separate cookies. Either way, what are the name(s) and value(s) that we should be setting on the cookie(s)?

Erich Schulz’s picture

Hi Tyler - see the posts 2-4

you dont have to do anything with cookies - just grab a token and place the token in you http headers

mxh’s picture

I agree with ivanbueno and childersc. This should have been configurable and not this abrupt way implemented. At least there should have been a clear documentation, referenced in the security announcement.

This change could have brought critical consequences, fortunately I tested it on dev environment before.

aakkawi’s picture

Category: support » bug
Status: Fixed » Active

@tyler_frankenstein

here you go :
https://drupal.org/node/910598

you just have to build the cookie from the sessionid and the session_name fropm the data object when the user logs in, dont forget the "=" between them in the cookie".

var cookie = data.sessid+"="+data.session_name ; //save this cookie as string for later use.

after sucsessfull login, create this cookie, then call the token service, save it also, then send both cookie and token in each request in the header.

ygerasimov’s picture

Category: bug » support
Status: Active » Fixed

I have added Change Notice https://drupal.org/node/2018963

Please advise whether text is clear and enough. Will need to update Handbook as well.

ygerasimov’s picture

joachim’s picture

Category: bug » support
Status: Active » Fixed

I'm a bit confused about this:

> have introduced another validation mechanism for non-safe REST calls (http method POST, PUT, DELETE)

> Now in order to do POST request Services expect X-CSRF-Token header

Is it only POST, or also PUT and DELETE?

ygerasimov’s picture

It is all three: POST, PUT, DELETE

joachim’s picture

The example code at https://drupal.org/node/1334758 fails at the first die, for the call to user/login. The curl error message is: 'The requested URL returned error: 401'

I am also trying to implement this for Clients module, and there I am finding that the token I receive from the menu path 'services/session/token' is not the same token that _services_sessions_authenticate_call() is trying to compare with.

ygerasimov’s picture

@joachim, when you are logged in you need to provide your cookie to the call to get a token as it is based on your session. I have updated code https://drupal.org/node/1334758. Does it help?

joachim’s picture

Ah, that was it! Thank you! :)

Another thing: does the initial user login at https://drupal.org/node/1334758 need a CSRF header token? I am finding it works fine without it in my code.

mxh’s picture

Nope, it doesn't need a token from the guest account when you login first.
You fetch the session id by calling user.login (as usual), and then you have to get the token (with the session id in the request header). After this, session id and token need to be set in the request header for all further remote calls. That's how it works on my clients.

giorgio79’s picture

Thanks for the sample code at https://drupal.org/node/1334758. For some reason my csrf token is always empty in the sample code, and I get a 401 on node create. Login works fine. Any tips?

PS: Here is a working php rest client
https://github.com/RandallKent/DrupalREST.PHP/issues/2

giorgio79’s picture

Anonymous users are not getting a token, but they can have permission to post content. Is this a bug in Services that anonymous users are not getting a csrf token?

l_o_l’s picture

In comment #25:

var cookie = data.sessid + "=" + data.session_name;

CORRECTION

Took we a while to figure this one out...
But it should be the other way around:
var cookie = data.session_name + "=" + data.sessid;

TeotiGraphix’s picture

Hi,

I can say this;

when you are logged in you need to provide your cookie to the call to get a token as it is based on your session

This was exactly what I was failing to do, pass the cookie header to the GET call of the token retrieval.

FYI, I am using Java XMLRPC and this example; https://drupal.org/node/1267522

I have successfully reworked that code to work with services 3.4 and the CSRF token. I might put a little project up in my github account of a full working Java example for those that want to see exactly how to get it working.

I spent a whole day with scattered documentation getting to this point, so I can imagine what others trying to get Java working might be feeling with the newer versions of Services.

Mike

ashergwebb’s picture

I have an issue. X-CSRF-Token header field is not accepted as part of Access-Control-Allow-Headers. Where is the appropriate place to put this directive on the server, and how would one do so.

ashergwebb’s picture

I have an issue. X-CSRF-Token header field is not accepted as part of Access-Control-Allow-Headers. Where is the appropriate place to put this directive on the server, and how would one do so.

ashergwebb’s picture

I have an issue. X-CSRF-Token header field is not accepted as part of Access-Control-Allow-Headers. Where is the appropriate place to put this directive on the server, and how would one do so.

joachim’s picture

Might I point out that the change record (at https://drupal.org/node/2018963) and the documentation (at https://drupal.org/node/1334758 and elsewhere) can be updated by **ANYONE**.

If you find mistakes or omissions, it is much more useful to update those. You're free to comment here, but updating the change record and the documentation will be **much more useful** both now and in the long run. People will be reading those. They won't be wading through a very lengthy issue thread.

ashergwebb’s picture

I am getting the error:
Refused to set unsafe header "Cookie"

Here is the ajax
$.ajax({
url: "?q=myservice/user/login.json",
type: 'post',
data: 'username=' + encodeURIComponent(name) + '&password=' + encodeURIComponent(pass),
dataType: 'json',
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('page_login_submit - failed to login');
console.log(JSON.stringify(XMLHttpRequest));
console.log(JSON.stringify(textStatus));
console.log(JSON.stringify(errorThrown));
},
success: function (data) {
console.log(data);
var cookie = data.session_name + "=" + data.sessid;
$(".usrTitle").html(data.user.name);
$.ajax({
url:"?q=services/session/token",
type:'get',
async:true,
crossDomain:true,
beforeSend: function (request) {
request.setRequestHeader("Cookie", cookie);
},
error: function(){
alert("error");
},
success: function(token){
alert("success");
console.log(token);
baSessionToken = token;
console.log(baSessionToken);
// return baSessionToken;
showToken(baSessionToken);
}

});

l_o_l’s picture

Refused to set unsafe header "Cookie"

Search for it on Google: its a problem that seems specific for Google Chrome. The solution is then simple: switch to another browser.
Also see this thread https://drupal.org/node/1133084

jbeuckm’s picture

@ivanbueno, your sequence works for login. What requests in what order are now required for user/register?

ashergwebb’s picture

I wish it were so easy as that I could tell my clients that...

ashergwebb’s picture

To me this seems it would be a huge deal for services! It seems it is not only chrome, but webkit browsers in general. This means 98% of mobile browsers will not work with session authentication with services module. It seems like in some ways it defeats the point of services or severely limits it. Is there any way the CSRF token auth system could just provide for a request header storing the session name and ID that is not "Cookie"? "X-CSRF-Token" works fine -- why not X-Cookie for the services module. It is frustrating because it works on non-webkit browsers as well as chrome extensions such as Postman. I can't seem to see any workaround. It clearly states here http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method that request header "Cookie" should terminate the XMLHttpRequest. Any suggestions as discarding 98% of mobile browsers and phone gap mobile apps is really hard to do as a developer.

marcus178’s picture

This update doesn't seem particularly friendly to those using services to provide data to mobile apps. Upgrading to this version breaks any existing coding and you would have to hope that all users will upgrade their app to the latest version otherwise it won't work any more.

scarer’s picture

I am having lots of difficulty with user login. I have tried the suggestions here and none seem to have worked so far. Has anyone managed to successfully log in using the Firefox add on poster? If so, what did you do? Thanks in advance.

EDIT #1: I ended up re-creating a new server with services and it seems to be responding now.

Also, if you're doing any sort of calling from a mobile device to the service make sure your web host php version is upgraded to PHP 5.3.

Now I'm having problems with the node->create. I'm passing it the Cookie as a header in the format session_name=session_id along with the session token in the header as X-CSRF-Token. It doesn't seem to like it. Any other suggestions for getting node->create working?

EDIT #2: If you're pushing from a native app on a mobile device you have to generate a new session token each time you make a request but you can still use the persistent cookie if the user is still logged in.

l_o_l’s picture

I also found it problematic to debug calls to Services from within a browser: the browser did not accept my javascript code to set (= change) the value for cookie. To work around it I created a function for Drupal that hooks the authentication in Services with MYMODULE_authenticate_call($settings, $method, $args). Inside this function I replace the 'official' cookie with the value of my custom cookie named 'mycookie':

   if (isset($_SERVER['HTTP_MYCOOKIE']) AND !empty($_SERVER['HTTP_MYCOOKIE'])) {
    $_SERVER['HTTP_COOKIE'] = $_SERVER['HTTP_MYCOOKIE'];
    $list = explode('=', $_SERVER['HTTP_MYCOOKIE']);
    $_COOKIE = array( $list[0]=>$list[1]);

Please be reminded: the value for mycookie still has to be valid in combination with the X-CSRF-Token.

revnoah’s picture

I'm still working through some issues but this is how I modified the accepted headers in Drupal. I added a short function to my custom Drupal module:

EDIT: I forgot these comments aren't threaded. This is in response to #40.

function custom_module_init() {
    drupal_add_http_header('Access-Control-Allow-Headers', 'X-XSRF-Token,X-CSRF-Token,Content-Type');
}
joachim’s picture

I've got working code in a patch for Clients here #2014131: update for X-CSRF-Token in Services REST 3.4 if anyone's interested in following that as an example. It's working fine, but I can't commit it till #2033843: make a new release is released.

ChrisValentine’s picture

In response to marcus178's post #47, I'm currently developing an HTML5 widget to go in an iBook, so my users would face exactly the same issues - but would be far less likely to know that a new release might be available to fix it. I can log in and grab the token fine but can't get either the request.setRequestHeader("Cookie", cookie); or beforeSend X-CSRF-Token approaches to work when trying to create a node.

nimbuz77’s picture

I'm using services 3.5 and I'm getting some troubles with rest server and session authentication.
I spent a day in trying many solution found on forum and documentation but I still get the "CSRF validation failed" error.
These are the steps I'm using to test (with curl) my back end.

# Login
curl -v -i -H "Content-type: application/json" -c cookies.txt -X POST -d '{"username":"myusername","password":"mypassword"}' "$login_url"

# Getting token
token="$(curl "$token_url")"

# Perform acrton -> this action will store data in a custom table in dB
curl -v -i -H "X-CSRF-Token: $token" -H "Content-type: application/json" -b cookies.txt -X POST -d '{"name":"myname", "surname":"mysurname", "email":"myemail"}' "$action_url"

Is there a workaround to solve my problem?

marcingy’s picture

Category: support » task
joachim’s picture

> token="$(curl "$token_url")"

The new user/token resource that Services has as of 3.5 doesn't return just a plain text token, it returns JSON which decodes to an object with a 'token' property. That might be your problem.

That certainly tripped me up while working on #2014131: update for X-CSRF-Token in Services REST 3.4 -- where there is now a complete patch btw :D

nimbuz77’s picture

The new user/token resource that Services has as of 3.5 doesn't return just a plain text token, it returns JSON which decodes to an object with a 'token' property. That might be your problem.

It seems to be a plain text, this is the bash code:

token_url="http://localhost/mysite/services/session/token"
token="$(curl "$token_url")"
echo $token

And this is the output:

man-10-21-80-20:api-test$ ./api_test.sh 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    43  100    43    0     0    433      0 --:--:-- --:--:-- --:--:--   443
4e6AYv58wyHZAk8wbpAY5oQ7D7H2UtnGpUNhRnk1dL8

However, I see the patch, how can I install it?
Is the new release coming in few days? I can wait the full new release if it will be deployed in few days

Thank you

tyler.frankenstein’s picture

@joachim, with Services 3.5, is there a particular time when it is appropriate to use the ?q=services/session/token vs. ?q=my_endpoint/user/token ?

EDIT

@nimbuz77, the ?q=services/session/token still returns a plain text token. The NEW user token resource returns the token bundled in an object. I misread it at first too and thought ?q=services/session/token would return an object with a token property.

joachim’s picture

> there a particular time when it is appropriate to use the ?q=services/session/token vs. ?q=my_endpoint/user/token ?

They do the same thing.
Over at Clients, we have to use the endpoint, as given an endpoint like www.example.com/mysite/myendpoint, you can't deduce the base URL of the site to get use the services/session/token menu path.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

revnoah’s picture

I ended up needing to make several changes to the header in my custom module, and I wanted to share it in case it helps someone.

function module_init() {
    drupal_add_http_header('Access-Control-Allow-Headers', 'X-CSRF-Token,Content-Type');
    drupal_add_http_header('Access-Control-Allow-Origin', 'http://frontend.server.com');
    drupal_add_http_header('Access-Control-Allow-Methods', "GET, PUT, POST, OPTIONS, DELETE");
    drupal_add_http_header('Access-Control-Allow-Credentials', 'true');
}

So now, logging in works as expected and the rest server respects Drupal's user permissions. But I'm actually having a problem with logging out, receiving a 406 error (malformed request). I'm setting the following parameters via Angular, similar to jQuery:
server: http://service.server.com/rest/user/logout.json, method: post, withCredentials: true (cookie set on login), header: X-CSRF-Token: (token received on login, added to request header).

I'm curious whether anyone else ran into issues with logout.

Chipie’s picture

Title: getting 'CSRF validation failed' since update to 3.4 » need Change Record for changes CSRF - 'CSRF validation failed' since update to 3.4
Component: Code » Documentation
Assigned: Unassigned » RamboLau
Category: feature » task
Priority: Normal » Critical
Status: Active » Closed (fixed)

> there a particular time when it is appropriate to use the ?q=services/session/token vs. ?q=my_endpoint/user/token ?

They do the same thing.

Are they really doing the same thing?

When I call ?q=my_endpoint/user/token I get an HTTP 401 error:

curl -i -H "Content-type: application/json"  -b cookies.txt http://example.com/my_endpoint/user/token

HTTP/1.1 401 Unauthorized: Access denied for user Stéphane

Using ?q=services/user/token I get the token:

curl -i -H "Content-type: application/json" -b cookies.txt  http://example.com/services/session/token

9bu7zAwPOccdU39w2UThcX5vSEdfjf4dpBZvePL8KeY

Why do I get different results?

joachim’s picture

> ?q=services/session/token vs. ?q=my_endpoint/user/token

They perform the same function, in that they get you a token.

However, the actual format of what they return is different, and they differ in how they are called.

Also, the one on the endpoint is a resource that you have to enable.

(Could someone add this to the docs please?)

Chipie’s picture

Also, the one on the endpoint is a resource that you have to enable.

I have enabled it in the endpoint. Do you know, why I get an Access denied?

jca’s picture

#46

To me this seems it would be a huge deal for services! It seems it is not only chrome, but webkit browsers in general. This means 98% of mobile browsers will not work with session authentication with services module. It seems like in some ways it defeats the point of services or severely limits it. Is there any way the CSRF token auth system could just provide for a request header storing the session name and ID that is not "Cookie"? "X-CSRF-Token" works fine -- why not X-Cookie for the services module. It is frustrating because it works on non-webkit browsers as well as chrome extensions such as Postman. I can't seem to see any workaround. It clearly states here http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method that request header "Cookie" should terminate the XMLHttpRequest. Any suggestions as discarding 98% of mobile browsers and phone gap mobile apps is really hard to do as a developer.

I have the same problem whith the 'unsafe cookie'

Anyone knows a work around???

I'm going crazy!!

l_o_l’s picture

Anyone knows a work around???

Yes, see [#49]

That does exactly what you ask: a hook which enables the use of a remote custom cookie and replaces it the very last minute (on the Drupal website) into the real Cookie. I used 'mycookie' in the example; please note that php will always add 'http_' in front so in the code its referred to as 'HTTP_MYCOOKIE'.

dobe’s picture

Issue summary: View changes

@Chipie I was running into the same issue. The patch found at https://www.drupal.org/node/2415503 should fix this.

dirckdigler’s picture

I can not grab the token via myservice/session/token, the browser does not show me anything, even poster firefox show me ["CSRF validation failed"].
I really dont understand why this happend to me, I know that I have to put the token on the header but my problem is I can not take the token.

version:
services = 7.x-3.12
oauth_common = 7.x-3.2
librarires = 7.x-2.2
token = 7.x-1.6

Anybody can help me?

hubobbb’s picture

$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
can solve the problem with JQ,you can see the answer on stackoverflow.com:

http://stackoverflow.com/questions/17975142/drupal-7-services-3-4-with-session-authentication-and-jquery

and if CORS, you must set the headers on your server program side ,set PHP HEADERS. items,suggest to use module http response header,modifye admin.inc file ,make its has these seleceted list and go to admin page to set value:
Access-Control-Allow-Origin:yoursite.com
Access-Control-Allow-Methods:GET, POST,PUT, DELETE,OPTIONS
Access-Control-Allow-Headers:Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-CSRF-Token
Access-Control-Allow-Credentials:true

My test code like this, in the actual situation login one time is enough , get the user token(data.token),you should save it and use it for the next auth. :

//get user ,cross domain  
var weixinhost="http://test.com";
 $.ajaxSetup({
            xhrFields: {
                withCredentials: true
            }
        });

$.ajax({
    url: weixinhost + '/weixinservice/node/user/token',
    type: 'POST',
    dataType: 'json',
    error: function onError(jqXHR, textStatus, errorThrown) {
        console.log(jqXHR);
        console.log(textStatus);
        console.log(errorThrown);
    },
    success: function(CSRFToken) {
        console.log('login chc suc');
        console.log("CSRFToken1:" + JSON.stringify(CSRFToken));
        var userName = "abc";
        var userPassword = "123qwe";
       
        $.ajax({
            url: weixinhost + '/weixinservice/user/login',
            type: 'POST',
            dataType: 'json',
            data: 'username=' + userName + '&password=' + userPassword,
            error: function onErroru(data) {
                console.log("user weixinapi fail");
                console.log(JSON.stringify(data));
            },
            //beforeSend: function (request) {
            //request.setRequestHeader('X-CSRF-Token', CSRFToken.token);
            //    },
            success: function(data) {
                console.log("1st:" + JSON.stringify(data));
                usertoken = data.token;
                console.log("usertoken:" + usertoken);
                $.ajax({
                    url: weixinhost + '/weixinservice/system/connect',
                    type: 'POST',
                    dataType: 'json',
                    error: function onErroru(data) {
                        console.log("user weixinapi fail");
                        console.log(JSON.stringify(data));
                    },
                    headers: {
                        'X-CSRF-Token': usertoken
                    },
                    /*beforeSend: function (request) {
                               request.setRequestHeader('X-CSRF-Token', usertoken);
                            }, */

                    success: function(data) {
                        console.log("2nd:" + JSON.stringify(data));
                    }
                });

            }
        });
argiepiano’s picture

Thank you, @hubbobbb! The first part of your comment allowed me to finally get the cross site request working. A quick note: the CORS module also allows you to set the headers on the server side, and does not require any of the "core hacking" of the admin.inc file in http_response_header module.

chinaphp’s picture

Well Done @hubbobbb! Thank you!

netake.nilesh’s picture

#2 worked for me , many thanks

databoy’s picture

Using the comment from #2 and the other code examples, I posted a sample PHP test in code over at https://www.drupal.org/node/790416#comment-11975936