I have been stuck on it for a while now. I cant understand what is the cause for it. Basically i am making a fetch request to my node js rest api(/csrf-token) to get the csrf token cookie and i am successful in doing so. But when i make a post request from the client it gives me invalid csrf token but that's the part i don't understand because when i open up my devtools i can clearly see an x-xsrf-token header along with _csrf cookie in the request. I would really appreciate if someone can help me point out where iam going wrong. I am using csurf library and below is my code:
Backend :
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.includes(origin)) {
console.log("Origin", origin)
callback(null, true)
} else {
callback(new HTTP401Error('Not allowed by CORS'))
}
},
credentials: true,
methods: 'GET,POST,PUT, DELETE, OPTIONS',
allowedHeaders: "Origin, Content-type, Accept, Authorization, x-xsrf-token"
}
app.use(bodyparser.json())
app.use(bodyparser.urlencoded({ extended: true }))
const csrfprotection = csrf({
cookie: true
})
app.use(cors(corsOptions))
app.use(helmet());
app.use(fileupload({
createParentPath: true,
limits: {
fileSize: 1 * 1024 * 1024 * 1024 //2MB max file(s) size
},
abortOnLimit: true,
}))
const sessionMiddleware = session({
name: process.env.SESS_NAME,
secret: process.env.SESS_SECRET,
resave: false,
rolling: true,
saveUninitialized: false,
store: store,
cookie: {
httpOnly: true,
sameSite: 'none',
domain: process.env.NODE_ENV === 'production' ? '.domain.com' : {},
secure: process.env.NODE_ENV === 'production' ? true : false,
maxAge: parseInt(process.env.SESS_LIFETIME)
}
})
app.set('trust proxy', 1);
app.use(sessionMiddleware)
app.use(csrfprotection)
app.get('/csrf-token', (req, res) => { // -->MY GET REQUEST WHICH SEND THE CSRF COOKIES
// res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.cookie('XSRF-TOKEN', req.csrfToken())
return res.status(200).json({
message: "success"
})
});
My frontend code :
const handleLogin = async () => {
const { csrftoken } = useSelector(state => state.csrfReducer)
try {
console.log("csrf token", csrftoken)
const result = await fetch('https://api.domain.com/auth/login', {
method: "POST",
body: JSON.stringify({
email: values.email,
password: values.password
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrftoken
},
credentials: "include",
})
if (result.ok) {
const data = await result.json()
console.log(data)
} else {
throw result
}
} catch (err) {
console.log(err)
}
}