I am trying to store JWt token in browser via cookies.
Post request on /login route in express is as follows:
const accessToken = jwt.sign({ email }, process.env.ACCESS_TOKEN_SECRET);
console.log(accessToken)
res.cookie('jwt', accessToken, { httpOnly: true })
// console.log("Cokkie set is", cookie);
res.json({ message: 'Logged in successfully' });
Axios call for frontend is as follows:
const res = await axios.post(
`${process.env.REACT_APP_API_URL}/login`,
{
email: loginInputs.email,
password: loginInputs.password,
},
{
// credentials: 'include',
withCredentials: true,
}
)
Cors policy is set as follows:
const corsOptions = {
origin: process.env.FRONTEND_URL,
credentials: true,
optionsSuccessStatus: 200,
// exposedHeaders: \['Set-Cookie', 'Date', 'ETag'\]
};
app.use(cors(corsOptions));
app.options('\*', cors(corsOptions))
This code works perfectly in Postman and the cookies are being set but throws the following error in browser.Currently both client and server work on local host!
login:1 Access to XMLHttpRequest at 'http://localhost:8080/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I tried everything mentioned in Express Session Cookie Not Being Set when using React Axios POST Request but was not able to resolve the error.
The origin
configuration of cors
middleware should be http://localhost:3000
, add the http
scheme. See Origin doc, the valid origin
syntaxes are:
Origin: null
Origin: <scheme>://<hostname>
Origin: <scheme>://<hostname>:<port>
A response that tells the browser to allow requesting code from the origin https://developer.mozilla.org to access a resource will include the following:
Access-Control-Allow-Origin: https://developer.mozilla.org
If the server sends the below response header to the browser.
Access-Control-Allow-Origin: localhost:3000
The client running on http://localhost:3000
send a HTTP request to http://localhost:8080/api/login
, the request header Origin
will be:
Origin: http://localhost:3000
Access-Control-Allow-Origin
does not match Origin
, the user agent will throw the CORS error.
The Origin
request header is added to the HTTP request by the browser automatically.
If a user agent needs to request resources included in a page, or fetched by scripts that it executes, then the
origin
of the page may be included in the request.
But your error message is: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'
If you want to send the cookie from the client to the server use the credentials: include
option for fetch
. Then don't set the origin
to wildcard '*'
and set the credentials: true
for cors
middleware.
E.g.
server.ts
:
import express from 'express';
import cors from 'cors';
const app = express();
const corsOptions = {
// set origin to a specific origin.
origin: 'http://localhost:3000',
// or, set origin to true to reflect the request origin
//origin: true,
credentials: true,
optionsSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.post('/api/login', (req, res) => {
res.cookie('jwt', '123', { httpOnly: true })
res.status(200).json({ message: 'Logged in successfully' });
})
app.listen(8080, () => {
console.log('Example app listening on port 8080!')
})
client/index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"
integrity="sha512-uMtXmF28A2Ab/JJO2t/vYhlaa/3ahUOgj1Zf27M5rOo8/+fcTUVH0/E0ll68njmjrLqOBjXM3V9NiPFL5ywWPQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
window.onload = function () {
// use fetch
fetch('http://localhost:8080/api/login', { method: 'POST', credentials: 'include' }).then(res => res.json()).then(data => {
console.log(data)
})
// use axios
axios.post('http://localhost:8080/api/login', {
withCredentials: true
}).then(res => {
console.log(res.data)
})
}
</script>
</body>
</html>
Start the API server:
$ npx ts-node server.ts
Example app listening on port 8080!
Start the web server:
$ npx http-server -p 3000 ./client/
Starting up http-server, serving ./client/
Available on:
http://127.0.0.1:3000
http://192.168.174.79:3000
Access the front end using URL: http://localhost:3000
Console logs:
{message: 'Logged in successfully'}