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

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?

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
)

Don't show error for self signed certificates in local network

I have a nodejs server that runs inside my network, and for security issues, there is no access to the internet.
The application needs to run in https, so I created a self-signed certificate and added it to my nodejs server:
const options = {
key: await fs.readFile(key, 'utf-8'),
cert: await fs.readFile(cert, 'utf-8'),
};
servers.https = https.createServer(options, this.app);
All this works fine, except when I open the app in the browser, I get a "Your connection is not private" warning, and the user needs to click "Advanced" and then "Proceed to localhost (unsafe)" to access the app.
What do I need to do so that the user does not receive this warning?
I understand the reasoning behind the warning, to prevent man-in-the-middle attacks, but because everything is running locally on my network, this is not a risk.
Any ideas or suggestions would be greatly appreciated, TIA!
This warning can not be disabled when using self signed certificates.
One possibility would be to use a local DNS and issue a Let's Encrypt certificate for it.

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.

Connect mqtt client via web sockets with HTTPS from browser

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

Will a Windows Store app always disallow a self-signed certificate even if explicitly trusted?

I've seen both this and this — same problem, different question.
I'm trying to connect my Windows 8.1 Store app to an ASP.NET Web API web service, secured over HTTPS using a self-signed certificate. It's a proof-of-concept application that will end up on < 5 different machines and seen only internally, so I was planning to just install the certificate as trusted on each of the target machines.
When I try this on my development setup, both HttpClient APIs fail to establish the trust relationship when calling the service.
Windows.Web.Http.HttpClient exception: "The certificate authority is invalid or incorrect"
System.Net.Http.HttpClient exception: "The remote certificate is invalid according to the validation procedure."
My self-signed certificate (public-key-only .cer version) is installed in both the "User" and "Local Machine" Trusted Root Certification Authorities on the client. I'm really surprised that this isn't enough to get WinRT to trust it. Is there something I'm missing, or is there just no way to set up the trust relationship for a self-signed SSL certificate that will make HttpClient happy?
Details on my setup:
ASP.NET Web API
Azure web role running in Azure emulator
Cert issuer: 127.0.0.1
Cert subject: 127.0.0.1
Cert key: 2048-bit
Windows 8.1 Store application
Certificate (.cer file with public key only) installed in User\Trusted Root Certification Authorities
Certificate (.cer file with public key only) installed in Local Machine\Trusted Root Certification Authorities
Certificate (.cer file with public key only) added to Windows Store app manifest under "CA"
I am not asking for a workaround to configure HttpClient to accept self-signed or invalid certificates in general — I just want to configure a trust relationship with THIS one. Is this possible?
You should be able to find out what is the problem with the certificate by doing a request like this:
// using Windows.Web.Http;
private async void Foo()
{
HttpRequestMessage request = null;
try
{
request = new HttpRequestMessage(
HttpMethod.Get,
new Uri("https://localhost"));
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendRequestAsync(request);
}
catch (Exception ex)
{
// Something like: 'Untrusted, InvalidName, RevocationFailure'
Debug.WriteLine(String.Join(
", ",
request.TransportInformation.ServerCertificateErrors));
}
}
Using a HttpBaseProtocolFilter you can ignore certificate errors:
// using Windows.Web.Http;
// using Windows.Web.Http.Filters;
// using Windows.Security.Cryptography.Certificates;;
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
HttpClient client = new HttpClient(filter);
HttpResponseMessage response = await client.SendRequestAsync(request);
The piece I was missing turned out to be that the certificate wasn't in the list of of IIS Server Certificates on my local machine!
Opening IIS Manager and checking out the Server Certificates section, I did find a 127.0.0.1 SSL certificate already set up by the Azure emulator:
CN = 127.0.0.1
O = TESTING ONLY
OU = Windows Azure DevFabric
However, my own self-signed certificate that I made outside of IIS, also with CN=127.0.0.1, was not in the list. I imported it, and now my Windows Store app's HttpClient connects happily (certificate warnings went away in Chrome and IE as well!)
If anyone can firm up the technical details on this, please comment — this fix feels a bit magical and I'm not sure I can pinpoint precisely why this worked. Possibly some confusion on my part between the two certs for 127.0.0.1, even though the thumbprint I had configured in my Azure project was always the one I was intending to use?

Resources