Home > Enterprise >  Cors error in client when calling mongodb database from backend
Cors error in client when calling mongodb database from backend

Time:07-25

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: '*'
}));
  • Related