Connect mqtt client via web sockets with HTTPS from browser - node.js

I would like to run a mqtt client on a web browser using web sockets with HTTPS. With HTTP, I have no problem. Here is the code on the web browser when using HTTP.
<script>
var client = mqtt.connect( 'wss://127.0.0.1:3000', {username:'test_user', password:'test_password'} );
client.subscribe("mqtt/test");
client.on("message", function(topic, payload) {
alert([topic, payload].join(": "));
client.end();
});
client.publish("mqtt/test", "testing hello world!");
</script>
This is how I start the stand-alone mosca broker to use HTTPS on websockets.
mosca --very-verbose --key ./tls-key.pem --cert ./tls-cert.pem --credentials ./credentials.json --https-port 3000 --https-bundle --https-static ./ | pino
How should I change my mqtt client code on the browser to connect to the Mosca broker on websockets via HTTPS?

As discussed in the other questions you have asked, the web browser has it's own list of trusted CA certificates, your self signed certificate will not be in this list so the connection is going to fail.
You can import your own trusted certs into your browser, but how to do this differs with each browser and you have to do it for EVERY instance of the browser so only really useful for individual testing.
If you need to allow members of the public (or browsers you can't install your certificate on) to connect to your broker then you will have to get a certificate from a recognised CA. You will have to either pay for this or use a service like http://letsencrypt.org

You have problems due to the use of self-signed certificate
Instead - you can use:
service cloudflare as front (with https and wss in free plan). Read about cloud flare
Get Temporary sertificates from letsencrypt (has a free plans). Read about letsencrypt
Get Trusted paid certificate

Related

Installing an SSL cert for NodeJs express (for API) on my Windows server

all my servers are hosted locally. I use IIS on server 2019 to host and manage my website. I use NodeJs to act as an API which makes queries to my SQL server to get the information and return it to my React app.
my react app calls out to my NodeJs API using fetch url
var url = 'https://example.com:8080/api/locationInfo/client?client=%';
fetch(url, {agent})
.then(response => response.json())
.then(data => setLocationInfoData(data));
since my website is using HTTPS, i must use that in the URL that reaches out to the API service from NodeJs.
right now when i attempt to make these API calls, console is giving me the error: net::ERR_SSL_PROTOCOL_ERROR
im assuming this is because my NodeJs app does not have an SSL certificate installed.
I've spent many (many) hours of research, but im not experienced with the backend of web development and im having trouble understanding where and how i apply an SSL cert to my NodeJs API. I used IIS to create a self-signed certificate, but it hasnt been applied anywhere and nothing else was done; im not sure where to go from here.
if it matters, my NodeJS API is hosted on the C:\Program Files[...] directory of the server, not under the actual web hosted directories.
If i place the NodeJs app within the actual web hosted directories, would i still need a certificate? If so, how do i export the .key and the .crt files to include in my NodeJs code?
please let me know if i can provide any more information or any of my code. My experience is limited, but im determined to learn and just need some pointers to send me in the right direction.
EDIT: i created a PFX cert from windows and used openSSH to convert the key, ca, and cert to .pem and included those in my nodeJs application. now im getting "ERR_SSL_KEY_USAGE_INCOMPATIBLE"
nodeJS code:
const sslServer = https.createServer(
{
key: fs.readFileSync(path.join(__dirname, 'cert', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert', 'cert.pem')),
ca: fs.readFileSync(path.join(__dirname, 'cert', 'ca.pem')),
},
app
)

Testing https API endpoint on localhost against a 3rd party app

I'm completely new to https and testing on localhost - please help!
What I'm doing
I'm trying to have a 3rd party app call my REST API endpoint, https://localhost:4000/test. This 3rd party only supports connections via https.
Problem
I'm trying to test this integration on localhost. To do this, I created a self-signed certificate using openssl. When this 3rd party service calls my endpoint, https://localhost:4000/test, it returns an error "Operation failed: Service is unreachable". On the docs, the error description is:
Error 400301: May be returned when executing Extensions, and the extension point did not respond.
Theory 1: The 3rd party doesn't trust my self-signed certificate (vs one from letsencrypt).
Clue #1: postman also didn't like my certificate and gave this error. I could only get it working by disabling the "SSL Validation" flag in Postman.
Clue #2: I put logs when my /test endpoint gets called on my server. But when the 3rd party triggers the event to call my API, nothing gets logged. It seems like they can't even start a connection to my server.
Theory 2: It doesn't support connections to localhost, only to endpoints deployed on the internet. Not sure how to test this theory other than actually deploying my API on the internet.
node.js snippet
https
.createServer(
{
key: fs.readFileSync("./my-private.key"),
cert: fs.readFileSync("./my-certificate.crt"),
passphrase: "secret",
},
app
)
.listen(PORT, () => {
console.log(`Listening on https://${HOST}:${PORT}`);
});
Command I used to sign my certificate:
openssl x509 -in my-request.csr -signkey my-private.key -out my-certificate.crt
One thing I noticed is that when I connect to https://localhost:4000 from Firefox, it tells me I'm not connected securely. Is this because the certificate is not signed by a 3rd party that the browser recognizes? How do I make this error go away?

Is it possible to ssl certify my nodejs backend to be possible to make https request to it?

I'm using a vuejs app deployed on GitHub pages, and I was using a nodejs backend in Aws EC2 which worked pretty well, but now pages wants me to use HTTPS requests, and I need to have a certificate. I tried with greenlock-express which didn't work,all requests gave some errors which I believe are because I am trying to certify a public IP address, and I need to certify a domain.
Then, my question is, how can I upload a backend for free (trial of a few days) and make it ssl certified to be able to receive and response https requests?
Thanks for your patience.
You can get a free SSL certificate from letsencrypt.org, then pass it to http.Server like this:
let app = express();
// ...
http.Server({
cert: "...",
key: "...",
ca: "...",
}, app).listen(443);

How to develop a https nodejs web app so that security warning doesn't show

I have changed the protocol on my website to http instead of https.
The following is my code that serves the server.
const https = require('https');
const httpsOptions = {
key : fs.readFileSync('example.key'),
cert : fs.readFileSync('example.crt')
};
https.createServer(httpsOptions, app).listen(port, ()=>{
console.log('server listening at 3000')
});
But now whenever I try to enter my locally run site https://localhost:3000, it shows security warning that the website is not safe anymore.
So I went to google docs https://developers.google.com/web/updates/2016/10/avoid-not-secure-warn to see how to remove the sign and it says 'create the entire website as https' but what I don't understand is all my sites are already https. To see all my views https must be used instead of http.
Is the above code not enough to make all the pages https? if it is, what else do I have to do so that I don't frighten my clients by showing warnings when they enter my site?
Your certificates are probably not signed, especially if you created them yourself, you need to send them to get signed by certified SSL certificated distributers. You can check this blog post for more info on certificate issuers.
Let's Encrypt is a free certificate issuer and you can automate the process of renewing them, so you don't have to worry on that part.

Node.js generate LetsEncrypt.org SSL certificate with specific common name

I am currently trying to create a LetsEncrypt SSL certificate package using the node letsencrypt package (https://www.npmjs.com/package/letsencrypt). I have managed to generate a standard certificate suite using the following code.
'use strict';
var express = require('express');
var LE = require('letsencrypt');
var le;
// server = staging for test encryption cert generation
// server = production for generating verified certificate
var le = LE.create({ server: 'production' });
// Define encryption certificate options as JSON object
var opts = {
domains: ['www.mydomain.com'], email: 'me#mydomain.com', agreeTos: true
};
// Submit certificate signing request to LetsEncrypt.
// Print certificates, keys (i.e. pem files) when received from server.
le.register(opts).then(function (certs) {
console.log(certs);
// privkey, cert, chain, expiresAt, issuedAt, subject, altnames
}, function (err) {
console.error(err);
});
var app = express();
// Create server listening on port 80 to handle ACME challenges
// i.e. basic web server to serve files so CA can verify website ownership
app.listen(80, function () {
console.log('Basic server started and listening on port 80');
console.log('Server handling basic ACME protocol challenges');
});
// Allow access to all static files in server directory
// Enables CA to access file served up to verify domain ownership
app.use('/', le.middleware());
Which works fine and generates me a trusted certificate from LetsEncrypt.org when accessed via www.mydomain.com. However, when I try to access my website on my internal (local) network via 192.168.0.myserveraddress. I get the following error:
Does anyone know how I can modify the common name in the certificate request to LetsEncrypt to 192.168.0.myserveraddress so I don't get this error when accessing my website via our local area network?
I actually solved this issue by setting up our local area network to allow loopback connections using what is called NAT Loopback.
This means I do not need to use the local IP address (192.168.0.myserveraddress) to access my server anymore and can just use www.mydomain.com to access it internally.
Since this maintains the domain name the certificate is now trusted and I no longer have the above error.
Additionally I believe that certificate authorities (i.e. LetsEncrypt) will not issue certificates for IP addresses. So the only way you can resolve the above error is to access the website via its domain name. See link below.
https://community.letsencrypt.org/t/certificate-for-static-ip/84.

Resources