Sorry if this is a noob question. What happens when the API call needs user's session. I assume those session cookies won't be forwarded to the API endpoint when the rendering happens on server-side?
Any idea on how should I forward user's cookies to the API endpoint. I think it will be somewhere inside HttpClient.js?
Thanks
@asadm it should be sending the cookies automatically (if you're doing a cross request make sure to add .withCredentials()), but the problem I'm having with this is that it doesn't work on the server side. I keep getting Error: Failed to serialize user into session when the server sends a login request. In the browser or with curl, the login request works fine, though.
Feel free to send a PR with axios or fetch etc.
@jaredpalmer I haven't figured out how to solve the problem yet, but I can try to work on a PR once it's fixed. :sweat_smile:
I'm getting the same error with fetch, by the way.
@jaredpalmer Sadly, not at all. This has to do with universal rendering, passport works fine. It also works fine to send requests from the browser or curl, just when the server in this boilerplate makes the request to get the initialState, it fails. I assume this is because the server-side doesn't store the user session. Is there any way to do this?
I think the easiest way to work around this issue is to return a token and store that in the state, then later authenticate requests with the token. Would be nice if client/server shared the correct user session automatically, though :smile:
This might be a related issue: http://stackoverflow.com/a/12735003/702288
can you link to an example repo? also are you using express-session?
@jaredpalmer Unfortunately I can't share the code, but it's not hard to add passport to your existing boilerplate: http://passportjs.org/docs
Yes I am using express-session. I have tried using superagent.agent(), but it didn't solve the issue.
@jaredpalmer I just cloned a fresh instance of your boilerplate and added express-session. Setting req.session crashes it (I did in src/server/api/posts.js). You can check this out in my fork omnidan/react-production-starter (relevant commit).
Ok, nevermind my issue seems to have been unrelated to this :blush:
I just found out that it couldn't serialize the user because the data was sent via json from the server, but urlencoded from the browser/curl. adding app.use(bodyParser.json()) to my server fixed the issue for me.
I still have the problem that the session doesn't seem to work correctly. I changed one request to be (for testing purposes):
callAPI: () => http.post('http://localhost:3003/login', {
email: '[email protected]',
password: 'test'
}).then(data => {
console.log('login', data)
return http.get('http://localhost:3003/user')
.then(data => console.log('user data:', data))
}),
The output of this is:
login { email: '[email protected]' }
user data: { error: 'Not authenticated, please log in.' }
If I do the /login request and then access /user in the browser, it works fine. Seems like the server isn't sharing sessions with the client properly.
I kinda solved it this way:
When user requests the page from express server. The req holds any session cookies in it's header. I just forward req.headers.cookie down till HttpClient.js:
get: (cookies, path) => new Promise((resolve, reject) => {
request
.get(getUrl(path))
.accept('application/json')
.set("Cookie",cookies)
.end((err, res) => {
if (err) {
if (err.status === 404) {
resolve(null);
} else {
reject(err);
}
} else {
resolve(res.body);
}
});
}),
Does this make sense?
@asadm good idea! I was gonna solve this by storing a login token in the redux store, but this is pretty much the same concept using cookies. I'll try this out in a bit :grin:
@omnidan I have done this approach and it's pretty similar to the one @asadm provided.
getWithToken: (path, token) => new Promise((resolve, reject) => {
request
.get(getUrl(path))
.set('X-User-Token', token)
.accept('application/json')
.end((err, res) => {
if (err) {
reject(err);
} else {
resolve(res.body);
}
});
})
Most helpful comment
@omnidan I have done this approach and it's pretty similar to the one @asadm provided.