Having a problem securing an Express API with TLS - node.js

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());

Related

Disable TLS 1.0 & 1.1 OR only use TLS 1.2 and greater in Node.js Express

How can I block TLS 1.0 and TLS 1.1 on my Node.js Express server? I'm using a traditional server setup script:
const app = express();
export const server = app.listen(3000);
I'm slightly confused why I couldn't find any documentation on this.
Usually you will be running your Express server behind something else, like an Nginx proxy, an AWS Load Balancer, or some other piece of software or hardware that terminates TLS. In your example, you're not listening over HTTPS at all, you're listening for HTTP connections on port 3000. The configuration would usually be done outside of your Node app, but if you do want to do it in your Node app, it would be like this:
const express = require('express')
const https = require('https')
const fs = require('fs')
const { options } = require('crypto')
const app = express()
const opts = {
key: fs.readFileSync('/path/to/key.pem'),
cert: fs.readFileSync('/path/to/chain.pem'),
secureOptions: constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1,
}
// other app logic
// Or 443 if you run it as root, which is not recommended;
// instead you should proxy to it.
https.createServer(opts, app).listen(3443)
ex.
const https = require("https");
const https_options = {
pfx: fs.readFileSync(path.join(__dirname, "../ssl/cert.pfx")),
passphrase: "password",
minVersion: "TLSv1.2"
}
server = https.createServer(https_options, app);
minVersion is the easiest way to accomplish this as mentioned here: https://stackoverflow.com/a/62051684/4487632

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

CORS giving issues once I went from localhost --> heroku

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.

node.js https server not loading responding

I am trying to start a https node.js server.
I started by creating a certificate and key following this guide:
http://gaboesquivel.com/blog/2014/nodejs-https-and-ssl-certificate-for-development/
and I placed them in my /app_name/security/keys directory.
To start my https server, I have the following:
const https = require('https'),
fs = require('fs');
if(app.get('env') === 'development') {
console.log('dev env!!'); //prints correctly
console.log('port: ' + port); //prints correctly
const options = {
key: fs.readFileSync('./security/keys/key.pem'),
cert: fs.readFileSync('./security/keys/cert.pem')
};
https.createServer(options, (req, res) => {
console.log('https good to go'); //this does not print out anything
}).listen(port);
}
When I go to https://localhost:3000, the page throws an error
This site can’t be reached
localhost unexpectedly closed the connection.
ERR_CONNECTION_CLOSED
But there's no error on the server side console. Furthermore, if i go to the regular localhost:3000, I get:
The localhost page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
Can someone help?
Thanks in advance!
---- UPDATE ----
I'm running on port 443 now. Initially I got an error:
Error: listen EACCES 0.0.0.0:443 so I ran:
sudo NODE_ENV=development nodemon app
Which did not throw any errors. However, when I went to https://localhost:443, I get:
This site can’t be reached
localhost unexpectedly closed the connection.
I used express as a web server.
to install express:
npm install express --save
I took your code, added the usage in express, generated certificate using openssl, and executed it - all looked good, the server was up, listening to port 3000 over https.
My code (which is based on your code...):
var app = require('express')();
const https = require('https'),
fs = require('fs'),
port = 3000;
if(app.get('env') === 'development') {
console.log('dev env!!'); //prints correctly
console.log('port: ' + port); //prints correctly
const options = {
key: fs.readFileSync('/tmp/private.key'),
cert: fs.readFileSync('/tmp/publickey.crt')
};
https.createServer(options, (req, res) => {
console.log('https good to go'); //this does message appears!!! ^_^
}).listen(port);
}
Please pay attention to the way I defined app: var app = require('express')();
You can split this definition into two line if it's more readable:
var express = require('express');
var app = express();
So many problems with your code.
I tested this really quickly.
the keyword app and port is not defined, lines 4 and 7 respectively.
That will throw you a syntax error, preventing the code from continuing any further therefore server not starting up at all.
As I mentioned on my comment, use devtool to debug and use the following line on a CLI devtool server.js -w where the -w watches for file changes and reloads the server on the fly, while developing.
also assuming you named your entry file server.js

Express HTTPS - unable to connect securely- SSLv3 broken protocol

Trying to make HTTPS server work on Express 4, however, there's an SSLv3 security error coming (please see the image). To my understanding SSLv3 protocol is not supported by browsers anymore due to POODLE attack.
How to make HTTPS server use the TLS1.2 protocol?
var express = require('express'),
app = express(),
fs = require('fs'),
https = require('https'),
key = fs.readFileSync('/usr/local/etc/ssl/key.pem'),
cert = fs.readFileSync('/usr/local/etc/ssl/cert.pem'),
https_options = {
key: key,
cert: cert
},
PORT = 8000,
HOST = 'localhost';
https.createServer(https_options.key, app).listen(PORT);
app.get('/', function(req, res) {
res.send('Hello');
});
module.exports = app;
The server is listening localhost:8000
The error
try to create server like that
it is working fine at my side,
var server = require('https').createServer(options, app),
server.listen(port);
or if like to add socket
var server = require('https').createServer(options, app),
io = require('socket.io').listen(server);
server.listen(port);

Resources