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);
});
}
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.
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.
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)
}
}
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
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With