Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs won't set cookie for React CRA application even with proxy

I have a nodejs/express + React CRA application, and I'm trying to set a cookie from nodejs. The server is on port 4001, so in my React application's project.json I have "proxy": "http://localhost:4001" set, but the cookie still won't get set in the browser.

I've tested it in production mode as well, with the React application being served from nodejs directly and it all works fine there.

Here is how I am setting the cookie. I've tried several different combinations of options here and they all have the same result.

res.cookie('jwt', token, {
    httpOnly: false,
    sameSite: false,
    signed: false,
    secure: false,
    encode: String
});
res.header('Access-Control-Allow-Credentials', 'true');

Edit: On the client side I am using Axios for my ajax requests.

Edit:

Here is the endpoint function for login (POST /api/users/login):

login: function(req, res) {
    User.findOne({
        $or: [{email: req.body.username}, {username: req.body.username}]
    }).exec().then(user => {
        if(user) {
            if(user.checkPassword(req.body.password)) {
                jwt.sign({ userID: user._id }, 'secret', (err, token) => {
                    res.cookie('jwt', token, {
                        httpOnly: false,
                        sameSite: false,
                        signed: false,
                        secure: false,
                        encode: String
                    });
                    res.header('Access-Control-Allow-Credentials', 'true');
                    res.status(200).send({ status: 'ok', message: 'Success'});
                });
            }
            else {
                return res.status(401).send({ status: 'error', message: 'Invalid username/password combination. Please try again.' });
            }
        }
        else {
            return res.status(401).send({ status: 'error', message: 'Invalid username/password combination. Please try again.' });
        }
    }, err => {
        return res.status(500).send({ status: 'error', message: 'unexpected error' });
    });
}

Here is the client-side login code:

login(username, password) {
    return new Promise((resolve, reject) => {
        axios({
            method: 'post',
            url: 'http://localhost:4001/api/users/login',
            data: {
                username,
                password
            }
        }).then((res) => {
            resolve(res.data);
        }, (err) => {
            reject(err);
        });
    });
}

Server is on port 4001, React CRA server is on 3000

like image 514
chrispytoes Avatar asked Nov 16 '18 15:11

chrispytoes


People also ask

Does proxy work in production React?

In production we can't use (proxy).. instead we can set a variable in the frontend for the backend URL, and vise versa.

Where do I put proxy in package JSON in React?

To configure the proxy, you'll need to add the following line to your package. json . Then, in your React app, you can make API requests by using relative paths. For example, http://localhost:8000/api/todos becomes /api/todos .

How do I get browser cookies in react JS?

Just run npm install [email protected] , add import cookie from 'react-cookie' to you file and use cookie. load('connect. sid') to get cookie value. You can check the README of v1 for detail.


1 Answers

To allow the browser to set cookies and adhere to Same Origin Policy, your client code should query http://localhost:3000/api/users/login (same host as client) instead of the (proxied) server url (port 4001).

You can also specify the base url as ${window.location.origin}/api or just /api.

like image 171
Roy Wang Avatar answered Oct 11 '22 03:10

Roy Wang