Send GET request from Amplify service to EC2 machine - node.js

< I am a real newbie so I am sorry if I am using the terms incorrectly. >
Hey guys!
I am trying to deploy my website, I put my front - files in Amplify app which provides me with an HTTPS url.
My goal is to load my backend code to EC2 ubuntu machine and to run it via pm2.
I have a trouble understanding how to do it, I am writing backend code in nodejs and I am using the express framework.
When I am developing locally, it all runs perfectly.
My backend code :
app.get('/db', (req,res) => {
let ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
const params = {
TableName: "blablabla",
};
let itemObj = [];
ddb.scan(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
data.Items.forEach(function (element, index, array) {
itemObj.push(data.Items);
res.status(200).json(itemObj);
});
}
})
Relate front-end code :
function getData(username){
var xmlhttp = new XMLHttpRequest();
var url = "http://localhost/db";
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) { //request completed
result = JSON.parse(this.responseText);
blablabla
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
When I am using localhost url and run the server via my computer (npm start server..) I do get the data I am looking for on the amplify service.
But when I use the elastic IP addresses of the EC2 machine I get an error: "was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint, This request has been blocked"
Is there any way to allow those kind of requests?
Do I even use the correct IP of the EC2 machine?
It seems to me that if EC2 provided me an HTTPS address, it will works fine, am I right or it has nothing to do with it?
Thanks in advence.

It works on your local machine because you don't have an SSL certificate on localhost, so your frontend is not loaded over a secure connection. When you run the frontend from Amplify, you're connecting to the Amplify domain name via SSL (I expect the URL is something like https://master.randomalphanumericstring.amplifyapp.com). So your browser complains when that page tries to make an insecure connection to your EC2 instance.
You can work around this by changing your browser settings to allow mixed content. In Chrome, it's Settings->Site Settings->Insecure Content->Add site. But that's just a workaround for development, obviously that won't work for production.
You can't make an HTTPS request to an IP address. SSL certificates must be associated with a domain name. It's also not a very robust solution to have your backend depend on a specific IP address. You have a few options to address this:
Generate an SSL certificate and install it on your EC2 instance. You can't use AWS Certificate Manager with EC2, so you'd need to obtain a certificate from letsencrypt or some other source. Self-signed won't work, it has to be trusted by the browser. And of course you need a registered domain for that.
Add an application load balancer with a secure listener and a certificate issued through ACM that directs requests to your EC2 instance. Again, you'll need to have a registered domain that you can use with the certificate.
Deploy your backend through Amplify. This will provide an API endpoint with a secure connection in the awsamazon.com domain.
There are many other ways to create an app backend with a secure connection, but those should get you started.

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
)

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

ASP.NET Core passing HTTP (not HTTPS) redirect URL in OAuth challenge when hosted in Linux container [duplicate]

This question already has answers here:
How to set redirect_uri protocol to HTTPS in Azure Web Apps
(8 answers)
Closed 3 years ago.
I have an implementation of Identity Server 4 which offers an option to sign in with Google. The app is registered with Google's developer console and has worked for some time when hosted on a Windows VM.
I've recently containerised this application and deployed it to a Linux container hosted as an Azure app service. I haven't changed any of the app code. The Azure app service is configured to serve HTTPS only, and I've verified the traffic is strictly secured with SSL certificates both between client browsers and Cloudflare (my DNS provider) and between Cloudflare and origin.
Here's what the Google OAuth button looks like. You can see it's a valid SSL connection:
Here's the code which registers this OAuth provider:
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = _externalAuthConfig.Google.ClientId;
options.ClientSecret = _externalAuthConfig.Google.ClientSecret;
});
I've confirmed the client and secret are valid. Here's the code executed when the button is clicked. You see this is all standard stuff.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[Route("challenge")]
public IActionResult ExternalLogin(
[FromForm] string provider,
[FromQuery] string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
However, in this containerized world, when the browser is redirected to Google, this is what I see:
Notice the http:// in the redirect URL. Obviously the error is occurring because I only registered the HTTPS redirect URL. The same code running on a Windows VM correctly passes an HTTPS redirect URL in the querystring. I have no idea why this unsecure URL is being used in this containerised environment. The only difference as far as I can tell is the hosting infrastructure.
In case it's important, this new site uses the built-in Kestrel web server, whereas the old Windows version used IIS in front.
Anyone have any idea? I'm stumped!
Typical, I found the solution in the answer from #FerronSW on this SO question 30 minutes after posting my question.
The solution is to add the following code to your Startup:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});
Tested and works.

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