Vincent
Vincent

Reputation: 5445

How to preserve session data in cross-origin requests?

I'm new to using Express and Connect, so I'm hoping I'm doing something stupid that has a simple solution.

Basically, I have a page where a user logs in using Persona. To validate authentication attempts, I use express-persona. Supposedly, this module saves the user's validated email address in a session variable (req.session.email, by default).

Now, after logging in, users can post a comment, and this comment will be saved together with the email address with which the user logged in. When the server that serves the form is the same as the one that handles the posting of the comment, this works fine. However, when they are different (let's say the user fills in the form at http://localhost:8001, whereas the browser then sends a POST request to http://localhost:8000 which should save the comment), all of a sudden the req.session.email value is undefined.

I think I set up Cross-Origin Resource Sharing correctly. The form is sent thusly (using jQuery):

$.ajax('http://localhost:8000/post/comment',
       {
           data: {comment: $('#commentField').val()},
           type: 'POST',
           xhrFields: {withCredentials: true}
       }
);

(Note the xhrField: {withCredentials: true} -- the session cookie is passed along, which I verified by inspecting the network request.)

The server sets up the (I think) correct CORS headers:

res.header('Access-Control-Allow-Origin', 'http://localhost:8001');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
res.header('Access-Control-Allow-Credentials', 'true');

When I add console.log(req.cookie), I see the sessionId cookie that has the same value as the one sent along with the POST request.

However: console.log(req.session.email) displays undefined for cross-origin requests -- again, it works fine when the requests come from the same origin.

What am I doing wrong?

Upvotes: 2

Views: 5210

Answers (2)

Henry Zou
Henry Zou

Reputation: 1917

For those who are looking to solve the same problem with Angular implementations. You can configure $http to send cookies using:

.config(function ($routeProvider, $httpProvider) {
    $httpProvider.defaults.withCredentials = true;
    //rest of route code

Upvotes: 3

Vincent
Vincent

Reputation: 5445

I found out my problem: I forgot to send cookies with the authentication request. Hence, the Express server could not identify the current user's session when logging in, and consequently could not save the user data to the session.

The solution was to also send the Persona assertion request with the withCredentials flag, as such:

var response = $.ajax(assertionUrl + '/verify', {
    data: {assertion: assertion},
    type: 'POST',
    xhrFields: {withCredentials: true}
});

(I don't think anyone will ever run into this exact same problem, but just in case...)

Upvotes: 7

Related Questions