CORS giving issues once I went from localhost --> heroku - node.js

I have a chat application where my client side is written in Reactjs and my backend is written in Nodejs/Express. I have required cors and everything on my backend and the entire application worked perfectly when I was using localhost:3000 for the client and localhost:5000 for the server. I then deployed the server to heroku and the client to netlify, and now I am getting this CORS error every time I try to log in using a POST request (using axios as well):
Under the network tab on chrome, I get two things, a "signin" that has 204 and it works, and then a "signin" that just says error.
This is what my backend looks like in Nodejs/express:
require('dotenv').config()
const http = require('http');
const cors = require('cors');
const hostname = '127.0.0.1';
const port = process.env.PORT || 5000;
const express = require('express');
const jwt = require('jsonwebtoken')
const cookieParser = require('cookie-parser');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const {AddUser, FindUser, RemoveUser, FindId} = require('./users.js')
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'] };
app.use(cors(corsOptions));
app.use(express.json())
app.use(cookieParser());
//Tells the server what port to listen to and can add a function to talk to command line
server.listen(port, () => {
console.log("Server is up!");
});
What I THINK might be the problem is maybe I'm not setting up the server using https, because I'm doing it with http. Maybe this is causing the problem but I don't know how to fix it. Other people have also mentioned it might not be a problem with CORS but rather Heroku, since Heroku only installs devDependencies or something like that, but I don't know how to fix that either.
I've tried adding headers, credentials, everything, I have no clue.
My front end looks like this:
const signIn = (e) => {
e.preventDefault();
axios.post('https://easytalkchatapp.herokuapp.com/signin', {
username: username,
password: password
}).then(res => {
...
and I have axios.defaults.withCredentials = true written at the top.
And just to re-state above, if I literally go to terminal and just run my server on localhost:5000 instead of heroku and make all my POST/GET requests through the localhost:500 server it works completely fine. If, however, I run my client on localhost:3000 and have the server be heroku, it breaks, so the problem is most certaintly with heroku and how I'm using it.

Since, you are using withCredentials, so I thinks its better to provide specific values for origin instead of true or '*' because it will not work with credentials true.
Try using this options:
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
};
I hope it helps.

if you use withCredentials= true and when you run frontend and backend both form localhost, it runs perfectly because they are in the same origin
but if you run frontend and backend from different origin(host) in that time it gives you cors issue. for resolve this issue you have to whitelist the frontend origin in the backend
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
};
by this way backend now trust the frontend origin

It turns out it was completely my own fault with my backend code. I was using process.env.(variable) and I had never specified it in the heroku config vars so it kept breaking when trying to access it. UGH. Thanks everyone.

Related

Cors Origin Error. Works on local but not when I deploy on heroku

I am using the code below to run my nodejs backend server. Angular front end has to communicate with the server. While I am using it on localhost everything works fine. However when I deploy my code on heroku I keep getting
Access to XMLHttpRequest at 'heroku app link' from origin 'https:https://iprocopiou.com/.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Does anyone know what I am missing here?
const express = require("express");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
const corsOptions = {
origin: "*",
methods: ["GET","HEAD","PUT","PATCH","POST","DELETE"],
credentials: true,
preflightContinue:false
}
require("./startup/logging")();
require("./startup/routes")(app);
require("./startup/db")();
require("./startup/config")();
require("./startup/validation")();
require("./startup/prod")(app);
app.use(cors(corsOptions))
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const port = process.env.PORT || 3000;
app.listen(port, () =\> console.log(`Listening on port ${port}`));
I have tried almost every solution that I found...
For security reasons you need to specify the exact URL or URLS origin (protocol + domain + port) when you want to allow and share credentials, you cannot use *.
const corsOptions = {
origin: "https://iprocopiou.com", // or your exact URL you allow to make request
methods: ["GET","HEAD","PUT","PATCH","POST","DELETE"],
credentials: true,
preflightContinue:false
}
//...
app.use(cors(corsOptions))
you can also see more detail in this threat CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true

Having a problem securing an Express API with TLS

I have a REST API running on Node JS with Express.
I keep having issues with CORS because the front end is HTTPS and the backend API is HTTPS which frequently, but not always gets reported as a violation.
I am trying to secure the API with a Let's Encrypt cert but I seem to be missing something.
Here is the code that initializes the express server:
require('dotenv').config();
const https = require("https"),
fs = require("fs");
const app = require("./src/app");
const port = process.env.PORT || 8000;
https
.createServer(
{
key: fs.readFileSync('/etc/letsencrypt/live/myserver.com/privkey.pem', 'utf8'),
cert: fs.readFileSync('/etc/letsencrypt/live/myserver.com/fullchain.pem', 'utf8')
},
app
)
.listen(8000, function() {
console.log('HTTPS listening on PORT 8000');
});
Is there another approach? Or am I just doing it wrong?
CURL still works on HTTP which surprises me. There shouldn't be an HTTP server listening on 8000. GET calls work without the SSL configuration but POSTs always fail.
All the APIs work locally, it's just when I push it to production that it fails. But then, locally, it's not running HTTPS so there is no violation.
I haven't seen posts that address this specifically so I have to wonder what I'm missing. This has to be a common scenario.
Thanks for any help.
Try either of these solutions, whatever suits you:
import * as Cors from 'cors';
const cors = Cors( { origin: true } );
app.use( cors );
var cors = require('cors');
var app = express();
app.use(cors());

How to make https work at nodejs and vue.js

I have a site written in Laravel and Vue.js, nodejs is also used. When I try to enter the site using the http protocol, everything is fine, when I try to enter the https protocol, half of the site does not load and in the console I get an error:
Access to XMLHttpRequest at 'https://example.com:8443/socket.io/?EIO=3&transport=polling&t=NPIJFIo' from origin 'https://example.com' has been blocked by CORS policy: No 'Access- Control-Allow-Origin 'header is present on the requested resource.
Redirection to https is configured on nginx itself, but I cannot do it on nodejs. Also i can't understand, how to correct add ssl cert path to my app.js.
My app.js:
const app = require('express')(),
server = require('https').createServer(app),
Redis = require('redis'),
RedisClient = Redis.createClient(),
io = require('socket.io')(server),
cors = require('cors'),
axios = require('axios');
const myArgs = process.argv.slice(2);
const domain = myArgs[0];
const SECRET_KEY = 'cZN^ZH8)mu~9e,>6M>3qKV=Ar^fFF,7/';
axios.defaults.baseURL = 'https://example.com/api/bot/';
server.listen(8081);
app.use(cors({
origin: true,
credentials: true
}));
What am I doing wrong? I would be grateful for help.
It's the CORS issue, and you need to add cors option for the socket.io server.
Refer to Handling CORS for Socket.io.
io = require('socket.io')(server, {
cors: {
origin: '*'
}
});

NodeJS, VueJS, express-session. Cookies don't set on client side

I work with app, that already has its own infrastructure. The task is to integrate session-cookie mechanism. I spent a lot of time to understand why cookies doesn’t set on client side.
I. Briefly.
App settings:
Server: NodeJS
Port: 8081
Client: VueJS
Port: 8088
I use module "express-session" to initialize session mechanism on server side and send cookies to client. Client hasn’t set cookies.
II. Details:
Server’s root file is index.js.
I do the following in it:
Plug in express module:
const express = require('express')
Plug in cors module:
const cors = require('cors')
Add cors settings:
app.use(cors({
origin: 'http://localhost:8088',
credentials: true
}))
Then I initialize session in user.js file and receive client’s connects:
Plug in express-session module:
const session = require('express-session')
Plug in routing by express.Router():
const router = express.Router()
Add session settings:
const EIGHT_HOURS = 1000 * 60 * 60 * 2
const {
SESS_NAME = 'sid',
SESS_LIFETIME = EIGHT_HOURS,
SESS_SECRET = 'test',
NODE_ENV = 'development'
} = process.env
const IN_PROD = NODE_ENV === 'production'
Initialize session:
router.use(session({
name: SESS_NAME,
resave: false,
saveUninitialized: false,
secret: SESS_SECRET,
cookie: {
maxAge: SESS_LIFETIME,
sameSite: false,
// Must have HTTPS to work 'secret:true'
secure: IN_PROD
}
}))
Receive client queries by router.post()
App client side consists of a lot of files. Client send data to NodeJS server by Axios module.
I read several articles by this theme and I guess that server side settings, which I made, are enough for work session-cookie mechanism. That means, that problem is on Vue side.
What I made:
I set in all files, where Axios send data to server, parameter withCredentials in true value (withCredentials: true) to pass CORS restrictions. This didn’t help
App in production has other URLs for accessing the production NodeJS server. I set develop NodeJS server URL in all client side files. This didn’t help
Read this article: Vue forum. From this article I understood, that need to solve this problem by axios.interceptors (StackOverFlow forum). I supposed that if this setting set on one of the client’s side pages, may be cookies should work at least on this page. This didn’t help.
Tried to set setting like this:
axios.defaults.withCredentials = true
And that:
axios.interceptors.request.use( function (config) {
console.log('Main interceptor success')
config.withCredentials = true;
return config;
},
function(error) {
// Do something with request error
console.log('Main interceptor error')
return Promise.reject(error);
}
)
This didn’t help
Please, tell me in which direction I should move? Is that right, that on client side on absolutely all pages must be axios.defaults.withCredentials = true setting to initialize cookies mechanism? What details I miss? If I set session-cookies from scratch the mechanism works.
I resolve this issue. I need to look for cookie storage in another browser place:
Chrome server cookie storage

Proxy in package.json not affecting fetch request

I am trying to fetch some data from the development server using React.
I am running the client on localhost:3001 and the backend on port 3000.
The fetch request :
const users = fetch('/api/users');
users.then((err,res) => {
console.log(res);
})
When I run my development server and webpack-dev-server I get the following output:
GET http://localhost:3001/api/users 404 (Not Found)
I tried specifying the proxy in the package.json so it would proxy the request to the API server, however nothing has changed.
Here is my package.json file:
.. and the webpack.config :
Please tell me, if you need to see anything else from my project. I apologies, if I'm missing something and not being thorough, I'm still quite new to using these technologies.
You can modify your fetch request API url to give the complete hostname since
fetch('http://localhost:3000/api/users')
also make sure that you have CORS enabled on your backend
In case your want to redirect through webpack, your can try devServer.proxy as
devServer: {
inline: true,
contentBase: './dist',
port: 3001,
proxy: { "/api/**": { target: 'http://localhost:3000', secure: false } }
}
I know I'm a little late to the game here, but I'll leave it here for future reference.
To make the devServer proxy work as expected, you need to specify the HTTP Accepts header to be something else than "text/html". Do this with the init-object that fetch accepts as the second argument. A simple example:
fetch("/api/profile",{
headers:{
"accepts":"application/json"
}
})
.then(res => {
console.log(res);
return res.json();
})
.then(json => console.log(json) )
.catch( a => { console.log(a) });
The reason for this is that the WebPack Dev Server normally uses a context/namespace to differentiate between what to serve and what to forward. The create-react-app scripts do not extract a namespace from the proxy path in the package.json file. Instead the scripts has the opinionated default behaviour that any request using something else than HTTP GET will get forwarded. Also, anything using HTTP GET, but NOT text/html as the Accepts header will get forwarded.
The reasoning is because most React Apps are SPA (Single Page Applications) which use AJAX/Fetch to communicate with some API. API's normally use JSON or XML, but not text/html.
In the package.json
"proxy": {
"/api/users": {
"target": "http://localhost:3000"
}
},
I had the same problem using axios and was only able to get it working by using the complete hostname and enabling Cors.
const response = await axios.get('http://localhost/users/');
Install cors
npm i cors
Use cors
const express = require("express");
const request = require("request");
const cors = require("cors");
const app = express();
app.use(cors());
app.use("/", (req, res) => {
//...
});
app.listen(80, () => {
console.log("CORS-enabled web server listening on port 80");
});
Ref
The solution by user jellyfish-tom in https://github.com/webpack/webpack-dev-server/issues/793#issuecomment-316650146 worked for me.
devServer: {
proxy: {
"*": "http://[::1]:8081"
// "secure": false,
// "changeOrigin": true
}
},
Webpack Dev Server uses devServer.proxy config in your Webpack config to control proxying requests.

Resources