Issue with API Endpoint /session/current


(Severe Overfl0w) #1

I have been having issues with the API endpoint /session/current is returning a 404 when I attempt to query this endpoint. I am able to access it directly in the browser (with the .json suffix). I have been using AngularJS’ $http and $resource modules to make my queries, however, this failing I tried using the sample code that @eviltrout provided in the thread:

 $.ajax("/session/current").then(function (json) { 
   console.log(json.current_user.username); 
 })

Attempting to use this against my Vagrant-VM URL (from Chromium console):

     > $.ajax("http://localhost:4000/session/current", {contentType: 'application/json'}).then(function (json) { 
       console.log(json); 
     })
Object {state: function, always: function, then: function, promise: function, pipe: function…}  // $.ajax immediate response
OPTIONS http://localhost:4000/session/current  jquery.js:8623
XMLHttpRequest cannot load http://localhost:4000/session/current. Invalid HTTP status code 404 

I am not sure how to proceed, so I am reaching out here for help! Any pointers?


(Kane York) #2

Try /session/current.json, seems like a request method sniffing failure to me.


(Severe Overfl0w) #3

I had tried .json in some of my other tests (Which I didn’t include). I’ll throw my server up in a little while and re-run the test above with .json for the sake of proof.

EDIT: Okay. Looks like Firefox and Chrome report different errors for the same issue, yippee. Did anybody ever mention that CORS is fun?

So, it seems like this is the current deal:
Chrome reports the 404 for this issue. Also, the console output from rails alludes to the issue being 404:

ActionController::RoutingError (No route matches [OPTIONS] "/session/current.json"):

However Firefox reports a CORS issue, I would assume this is down to the 404 page not returning the required CORS headers? Ergo causing Firefox to throw a CORS error so javascript can’t be used to brute force urls on other websites I assume. (Possibly a Chrome bug here, might have to check in with those guys at some point!).

So, I am now pretty lost, I have no Rails experience (I tend to do Python, not Ruby!), so I can contribute little in terms of debugging. Any pointers on my next step?


(Kane York) #4

So wait, you are querying it from another website? Why is this other website not same-origin?

I’m not exactly a fan of making the current user’s identify something that can be cross-site requested…

That’s exactly the kind of thing the same-origin policies are supposed to prevent. (Imagine an ad network grabbing your Discourse username…)


(Severe Overfl0w) #5

I am indeed. Discourse will be hosted on a subdomain, and I have a few extra pages I need elsewhere, but I’d like to maintain an integrated navigation bar between all pages, which also displays the currently logged in user.

The API exists already for this issue, see: How to get current user?

You can limit CORS to a particular domain. So I will just ensure that it only allows my domain to work in production.


(Robin Ward) #6

CORS is generally a huge nightmare to get working properly.

Any chance you could use python to make the HTTP request instead? You will likely find that much easier.

The endpoint is clearly working – it must be related to CORS or a cookie not being passed over or something like that.


(Severe Overfl0w) #7

I need to grab the current user, so it’s unfortunately a no. I need the info that is being provided by the users cookies, on the discourse subdomain, which I have no access to.

I have had some luck with CORS, I have been able to display a forum section’s posts on the homepage, which fails when I disable CORS. It’s just something particular about this API end-point.


(Kane York) #8

Perhaps you could do some magic with framing, and changing security context to the root domain, and passing a message in js?


(Severe Overfl0w) #9

Okay, so just had a look through the discourse code, and I realised that cookies weren’t being passed along. I went and had a look at the jQuery documentation and it said I needed to include the withCredentials header, to include cookies…

Adding the jQuery config didn’t seem to solve the problem however, so I have now done it in pure Javascript and set the withCredentials header, and it has worked.

A few notes:

  1. When using withCredentials the cors origin MUST be set to an actual value, not the wildcard *. (Solves the Ad Agency problem in a brutal way eh @riking)

  2. Here is my current code (compiled from coffeescript, excuse it a little!):

    var callOtherDomain, handler, invocation, url;

    invocation = new XMLHttpRequest();

    url = ‘http://localhost:4000/session/current.json’;

    handler = function(evtXHR) {
    if (invocation.readyState === 4) {
    if (invocation.status === 200) {
    console.log(invocation);
    return console.log(JSON.parse(invocation.response).current_user.name);
    } else {
    return console.log(‘Error’);
    }
    } else {
    return console.log(‘Not 4’);
    }
    };

    callOtherDomain = function() {
    if (invocation) {
    invocation.open(‘GET’, url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    return invocation.send();
    }
    };

    callOtherDomain();

  3. Firefox’s debug tools lie. Use Chrome’s.


(Robbo) #10

Okay so we have just had to deal with this issue as well and the above helped but just going to post jquery instead since it is a little more clear.

    $.ajax({
      url: forumUrl + '/session/current.json',
      dataType: 'json',
      // https://meta.discourse.org/t/issue-with-api-endpoint-session-current/20757/9
      xhrFields: {
        withCredentials: true
      },
      complete: handleHeartbeat
    });

So the xhrFields part here is what is required for this to work and also the .json explicit in the URL as the dataType is being ignored. Both of these things are bugs with discourse weather they admit it or not. But can be worked around easily so meh.

Also cors has to be set explicitly (as it always should be anyway) for this to work as mentioned in the post above.

And a note, there is a /my endpoint you can use to link to the current users pages. For example /my/preferences will redirect me to /users/robbo/preferences on here. This endpoint suffers from the same bugs this thread is about if you are doing request from ajax.