skip to Main Content

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 🙂

3

Answers


  1. Chosen as BEST ANSWER

    Solved!

    Turnes out in this case, the error is misleading at best. I had forgotten to add the new environment variables (env. variables to connect to database, and to use JWT) to netlify for deployment. When that was done, it worked without changing any more code. PS: all code was changed according to the answers above.

    Thank you to all the contributors :)

    Why this resolved in a cors error in google chrome, I dont know. :)


  2. 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: '*'
    }));
    
    Login or Signup to reply.
  3. 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
    app.use('/ip', ip);
    app.use('/youtube', youtube);
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search