I am having a problem with cors when I call my netlify hosted nodejs express backend from my react frontend.
im am getting the following errormessage in my web browser:
Access to XMLHttpRequest at 'https://<my_api_domain>/api/forgotpassword' from origin 'localhost:8888' has been blocked by CORS policy: No 'Access-
Control-Allow-Origin' header is present on the requested resource."
I have tried a lot of solutions with setting headers in the respons from my backend, but nothing seams to work. In localhost everything works fine.
the main file, api.js, looks like this:
'use strict';
const express = require('express');
const serverless = require('serverless-http');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const router = express.Router();
router.use(express.json());
const apiLimiter = require('../middleware/ratelimiter');
//import modules
const youtube = require('./youtube');
const ip = require('./ip');
const sendgrid = require('./sendgrid');
const sendinblue = require('./sendinblue');
const login = require('./login');
const forgotPassword = require('./forgotpassword');
const register = require('./register');
const test = require('./test');
require('dotenv').config();
router.use(helmet());
router.use(morgan('combined'));
router.use(cors());
//this part was added in order to try to fix the cors error
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization'
);
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, PATCH, OPTIONS'
);
next();
});
app.use(bodyParser.json());
router.use('/ip', ip);
router.use('/youtube', youtube);
router.use('/sendgrid', sendgrid);
router.use('/sendinblue', sendinblue);
router.use('/login', login);
router.use('/register', register);
router.use('/test', test);
router.use('/forgotpassword', forgotPassword);
app.use('/api', router);
// path must route to lambda
app.set('trust proxy', 1);
module.exports = app;
module.exports.handler = serverless(app);
The cors error only happens when I call the forgotpassword endpoint, which looks like this:
const express = require('express');
const router = express.Router();
//const { check, validationResult } = require('express-validator');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const connect = require('../functions/db');
const captcha = require('../middleware/captcha');
const sendMail = require('../functions/sendResetMail');
require('dotenv').config();
// get usermodel
const User = require('../models/User');
const Token = require('../models/resetPassword');
//@path: /forgotpassword
//@ public
router.post(
'/',
captcha,
async (req, res) => {
const { email } = req.body.data;
console.log(email);
connect();
try {
// See if user exists
const user = await User.findOne({ email });
if (!user) {
console.log('no user'); //fjernes
return res.status(200).json({
errors: [{ msg: 'If user Exists, an email will be sendt' }],
});
}
const extToken = await Token.findOne({ userId: user._id });
if (extToken) {
await extToken.deleteOne();
}
const payload = {
user: {
id: user._id,
},
};
const secret = process.env.JWT_RESET_PASSWORD;
const webToken = jwt.sign(payload, secret, {
algorithm: 'HS256',
expiresIn: 3600,
});
const salt = await bcrypt.genSalt(10);
const tokenHash = await bcrypt.hash(webToken, salt);
const token = new Token({
userId: user._id,
token: tokenHash,
});
await token.save();
res
.status(200)
.header('Access-Control-Allow-Origin', 'http://localhost:60427')
// several ways is tried of the above
.json({ link: webToken, url: UrlLink });
return;
} catch (err) {
res.status(400).json({ errors: [{ msg: err }] });
return;
}
}
);
i have figured out that the cors error only appears if from either when I make a call to the database (not when connecting) og if I try to use crypt. If I don't make a cal to the database, or encrypt with bcryept, the cors error will not appear in my web browser.
PS: my frontend and backend is hosted separately, so the domain is not the same.
any help to figure this out will be much appreciated :)
CodePudding user response:
I ran into this issue quite a bit I would make sure that you allow access at the very top of your server file so that its allowing access across all of your routes. Something like this
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((_, res, next) => {
res.set('Access-Control-Allow-Origin', '*'); // or 'localhost:8888'
res.set('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
res.set(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
return next();
}); // sets headers before routes
// routes start here
Make sure that if you're setting the response headers you're doing so BEFORE all of your routes. Most of the times I've struggled with CORS is because I was only setting it on some routes some of the time. This setup will ensure every route is g2g.
CodePudding user response:
You can mention the origins allowed as shown below
const cors = require('cors');
app.use(cors({
origin: ['http://localhost', 'https://localhost/']
}));
or for all origins
app.use(cors({
origin: '*'
}));