Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set cookies express, react.js

I am building a login system using express for node.js and react.js. In my back-end when a user logs in, it creates a cookie. When I go to Network > Login I can see this:

Set-Cookie:

user_id=s%3A1.E%2FWVGXrIgyXaM4crLOoxO%2Fur0tdjeN6ldABcYOgpOPk; Path=/; HttpOnly; Secure

But when I go to Application > Cookies > http://localhost:3000, there is nothing there. I believe that is because I am not allowing credentials to go through correctly when I do a post request from the client side. How do I go about this? Please, let me know if I can improve my question in any way.

//Login back-end
router.post('/login', (req, res, next) => {
    if(validUser(req.body)) {
        User
            .getOneByEmail(req.body.email)
            .then(user => {
                if(user) {
                    bcrypt
                        .compare(req.body.password_digest, user.password_digest)
                        .then((result) => {
                            if(result) {
                                const isSecure = process.env.NODE_ENV != 'development';

                                res.cookie('user_id', user.id, {
                                    httpOnly: true,
                                    secure: isSecure,
                                    signed: true
                                })
                                res.json({
                                    message: 'Logged in'
                                });
                            } else {
                                next(new Error('Invalid Login'))
                            }
                        });
                } else {
                    next(new Error('Invalid Login'))
                }
            });
    } else {
        next(new Error('Invalid Login'))
    }
});

//Allow CORS index.js
app.use(
cors({
    origin: "http://localhost:3000",
    credentials: true
})
);

//Login client side (React.js)
loginUser(e, loginEmail, password) {
e.preventDefault();

let email = loginEmail;
let password_digest = password;
let body = JSON.stringify({ email, password_digest });

fetch("http://localhost:5656/api/login", {
    method: "POST",
    headers: {
    "Content-Type": "application/json"
    },
    credentials: "include",
    body
})
    .then(response => response.json())
    .then(user => {
    console.log(user);
    });
}

like image 870
Windbox Avatar asked Dec 22 '18 17:12

Windbox


People also ask

How do you set cookies using react JS?

To set a cookie, we need to import the useCookies() hook from the react-cookie package. The useCookies() hook accepts the array with cookie-name as it's first argument and returns the array with two elements cookies object , setCookie() method. The cookies object contains all cookies you have created in your app.

How do I send cookies from server to client?

The Set-Cookie HTTP response header is used to send a cookie from the server to the user agent, so that the user agent can send it back to the server later. To send multiple cookies, multiple Set-Cookie headers should be sent in the same response.


2 Answers

You should be secure of set "credentials" in the server and in app.

Try to set on you index.js or app.js server side this:

  app.use(function(req, res, next) {
  res.header('Content-Type', 'application/json;charset=UTF-8')
  res.header('Access-Control-Allow-Credentials', true)
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept'
  )
  next()
})

and in you client site add options like this:

let axiosConfig = {
  withCredentials: true,
}

export async function loginUser(data) {
  try {
    const res = await axios.post(
      `${URL}:${PORT}/${API}/signin`,
      data,
      axiosConfig
    )
    return res
  } catch (error) {
    console.log(error)
  }
}

Edit

To set "credentials" in server we need this line:

res.header('Access-Control-Allow-Credentials', true)

This would let you handle credentials includes in headers.

You also have to tell to axios to set credentials in headers with:

withCredentials: true
like image 186
Ender Bonnet Avatar answered Oct 11 '22 07:10

Ender Bonnet


Do not forget to adjust cors middleware.

Your node.js express code

const express = require("express");
const cors = require('cors')

const app = express();

app.use(cors(
  {
    origin: 'http://localhost:3000',
    optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
  }
));

app.use(function(req, res, next) {
  res.header('Content-Type', 'application/json;charset=UTF-8')
  res.header('Access-Control-Allow-Credentials', true)
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept'
  )
  next()
})

app.get("/auth", function(req, res){

  res.cookie('token', 'someauthtoken')
  res.json({id: 2});
});

app.listen(3030);

Your front-end code

import React, { useEffect } from 'react';
import axios from 'axios';


async function loginUser() {
  try {
    const res = await axios.get(
      'http://localhost:3030/auth',
      {
        withCredentials: true,
      }
    )
    return res
  } catch (error) {
    console.log(error)
  }
}

function App() {

  useEffect(() => {
    loginUser();
  }, [])

  return (
    <div>

    </div>
  );
}

export default App;
like image 44
Сергей Седых Avatar answered Oct 11 '22 06:10

Сергей Седых