Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery Ajax Firefox not sending cookie (Chrome works)

I'm trying to use Ajax authentication in my app and I seem to have gotten it working, except firefox does not seem to be sending the correct jessionid to the server in the "cookie" request header for subsequent requests whereas chrome does so just fine. Here is the login function:

$.ajaxSetup({
    xhrFields: {
        withCredentials : true
    }
})
function sudoLogin(callback){

    $.ajax({
            url : HOST + "/ProperApp/j_spring_security_check",
            type : "POST",
            data : $("#login").serialize(),
            dataType: 'json',
            async : false,
            success: function(result) {
                if (result.login) {
                    callback(true);
                } else {
                    callback(false);
                }
            }
        })
}

In the response in firefox I can see the cookie being set, and the success callback is called:

Set-Cookie  JSESSIONID=81235e7ff741e941c1e078afee5c; Path=/ProperApp; HttpOnly

However, in subsequent requests, such as this one, the cookie is not being sent:

function getUserDeets(callback){
    $.ajax({
        url : HOST+ "/ProperApp/userData",
        type : "GET",
        async : false,
        dataType : 'json',
        xhrFields: {
                withCredentials: true
            },
        success : function(data){
            callback(data);
        }
    })
}
$('#submitLogin').click(function(){
            sudoLogin(function(loggedIn){
                if(loggedIn){
                    //window.location = "sudoIndex2.php";
                    getUserDeets(function(user){
                       alert(user);
                    })

                }
                else
                    alert("login failure");
            });
        });

In Chromium, the request contains the cookie header, and the success callback is called correctly:

...
Connection:keep-alive
Cookie:JSESSIONID=8129ef67b59180f9f21383cba850
Host:localhost:8080
Origin:http://localhost:8000
Referer:http://localhost:8000/loginSignup.php
...

However in Firefox, the request header does not contain the cookie header, and success is never called:

...
Connection  keep-alive
Host    localhost:8080
Origin  http://localhost:8000
Referer http://localhost:8000/loginSignup.php
...

Ive created a ajax filter on the server side, that I think should be allowing this to happen:

response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Max-Age", "360");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Authorization");

Any idea why this would work seamlessly in Chrome but not Firefox?

like image 484
Fingel Avatar asked Dec 01 '12 20:12

Fingel


2 Answers

If you wish to use native ajax or jquery ajax, then strip off async:false. it worked for me.

For further compatibility on older browsers i recommend using http://easyxdm.net/wp/. EasyXDM approach is to use an iframe hack that requires you to place an html file at the host that you're making ajax calls to. And this will be forcefully async, yes. But what's nice with this easyXDM is that you won't have to worry about cors headers.

like image 167
Thomas Vo Avatar answered Nov 13 '22 08:11

Thomas Vo


A couple of observations first:

  • The OP (original post) was dealing with cross-domain XHR because AustinR was using different ports (if any part of host, domain or port differ then the browser treats the XHR as cross-domain)
  • Cross domain XHRs need proper CORS headers to be set on the server
  • The javascript in the OP seemed fine except for the async:false which should ideally be set to async:true (or skipped because the setting defaults to true)

Referring to the given example I would start off with the following CORS headers:

response.setHeader("Access-Control-Allow-Origin", "http://localhost:8000"); // use a wildcard (*) as the 2nd parameter if you want to be less restrictive
response.setHeader("Access-Control-Max-Age", "360");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET");
response.setHeader("Access-Control-Allow-Headers", "Origin");
response.setHeader("Access-Control-Expose-Headers","Access-Control-Allow-Origin");

The last CORS setting "Access-Control-Expose-Headers" is especially useful because it gives you a chance to troubleshoot the headers that are sent in the HTTP response by the server.

Check the response header section in the Firebug network panel for the CORS headers. The "Origin" header of your request should match the pattern of the "Access-Control-Allow-Origin" header of the server response.

like image 4
marty Avatar answered Nov 13 '22 09:11

marty