SSL certificate propagation issue with custom domain on Bluemix app - node.js

I uploaded my SSL certificate in the section of my custom domain in the space of my organization. I linked the domain with my application and I have created the CNAME record in my DNS to my broken app xxxxx-gb.bluemix.net .eu.
When I try to reach my application through my domain custom, I served me the Bluemix certificate and not mine.
I tried to add a proxy on my server (NodeJS) but the situation does not change.
app.enable('trust proxy');
app.use(function (req, res, next) {
if (req.secure) {
// request was via https, so do no special handling
next();
} else {
// request was via http, so redirect to https
res.redirect('https://' + req.headers.host + req.url);
}
});
How can I fix the problem ? I need my certificate, to call my API, from my mobile application, it is the certificate must necessarily be mine and then TRUSTED

You need to map the CNAME to the secure endpoint for the Bluemix region you are using, in your case it should be secure.eu-gb.bluemix.net.
When receiving the request from your custom domain Bluemix will map it internally to your app.
More details in the documentation link below:
https://new-console.ng.bluemix.net/docs/manageapps/updapps.html#domain

Related

Send GET request from Amplify service to EC2 machine

< 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.

How to Restrict the anonymous domain accessing my webisite

! I have implemented a WebApp and SQL-DB.
added custom domain and SSL certificates (which bought at CA).
for SSL offloading purpose we configured an azure application gateway.
with all setup.
next, we configured azure traffic manager so that traffic manager decide active web app routing.
our concern is when I adding the CNAME record for traffic manager in GoDaddy it is routing to WebApp, everything is great.
but when I search "xxxx.com" Digwebinterface it shows all connections to WebApp
in this, I took the traffic manager CNAME record and added to another domain then the duplicate domain also accessing all my content of the website and even create a record in SQL also.
in this scenario I losing my website restriction unauthorized domain can map site
any suggestion and insights it would be grateful to
thank you
The simple way is to create a filter in your code for inspecting the host of headers of request to allow or deny the accessing from different domain.
Here is my sample code in Node.js with express.
const express = require('express')
const app = express()
const port = 3000
const allowedHosts = [`localhost:${port}`]
var domainFilter = function(req, res, next) {
if(allowedHosts.includes(req.headers.host)) {
next()
} else {
res.status(403).end()
}
}
app.use(domainFilter)
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
It will allow the request from localhost:3000 and deny the request from 127.0.0.1:3000 or others, as the figures below.
Fig 1. Allow the request from localhost:3000
Fig 2. Deny from 127.0.0.1:3000 or others
Hope it helps.

Express application for Authentication as seperate microservice

Current Situation:
I am currently working with a specific oauth provider and i am hosting my applications as microservices in a kubernetes cluster.
My end user is actively working with an angular application hosted as a docker container using nginx as webserver.
Now my idea was to integrate the authentication as a seperate microservice using node.js express and passport. so The workflow would be
User hits login in angular and gets redirected to the express application (same host address just a different endpoint /auth/someProvider)
The express application has no user interface it just handles all the oauth redirecting and communication with the provider, after the user information has been collected it redirects back to the angular application.
Now this works pretty for one last part. When my /auth/provider/callback would redirect inside of the express application it is very easy to access the request object that has been extended with the user object. when I redirect to an external website I get the cookie and everything but not an easy way to access the user object.
My acutal question(s):
Is there a safe way to pass that user information from the Request object directly to be used by the angular application (Best way i could think of is to use the headers as they are encrypted as well in https but still seems kind of hacky).
Is ita good idea in general to use OAuth that way.
The big advantage to this solution would be that I could use the same Docker Container with many web projects not having to implement Authentication one by one by just changing ClientId and Secret Env Vars in that Docker Container.
OK this is how I made it work.
basically you implement the basic concept described in the passport.js Documentation and add a seperate endpoint to access the userinfo. This is why I will describe where it starts to differ a bit
Step 1: Authenticate user at the Gateway
As described in the passport.js documentation. The authentication microservice needs the following callback (The router here is already served under /auth)
router.get("/provider/callback", passport.authenticate("provider", {
failureRedirect: "https://your-frontent-app.com/login",
}), (req, res) => {
res.redirect("https://your-frontend-app.com");
});
When you get back to your Web-Application you will see the Session-Cookie has successfully been stored.
Step2: Get User Info from Endpoint
Now we need the second endpoint /auth/userinfo in our routes.
router.get('/userinfo', (req, res) => {
if(!req.session) return res.status(401).send();
if(!req.session.passport) return res.status(401).send();
if(!req.session.passport.user) return res.status(401).send();
return res.json(req.session.passport.user).status(200).send();
});
Not very pretty this block with the 3 if's but it happened to me that all of those combinations could be undefined
Now, with the session cookie stored in our browser we can call that endpoint from our front-end with the credentials (I'll use axios for that)
axios.get('https://your-authenticator.com/auth/userinfo', {withCredentials: true})
.then(res => {
//do stuff with res.data
});
Now theres one more thing to note. If you want to use credentials to call that API setting the Access-Control-Allow-Origin Header to * will not work. You will have to use the specific host you'll be calling from. Also you will need to allow the Credentials in the Header. So back in your main Express app make sure you use the headers like
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://your-frontend-app.com");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Auth, Authentication, Authorization, Credentials");
next();
});

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.

Forbit CORS request in node.js

I have a nodejs Express app which serves a static front-end app. I have an endpoint that I'd like to prevent the access from all the others domains.
One solution could be using CRSF but I'd prefer avoiding this. Is there a simple way?
My app is very simple:
app.use(express.static(path.join(__dirname, '/dist')));
app.use(bodyParser.json());
app.post('/endpoint', (req, res) => {
res.send();
});
app.listen(process.env.PORT || 8080);
Does the domain have a static IP? You could add your domains IP to a whitelist blocking access to your endpoint from all IP's bar your own:
express-ipfilter
If you don't have a static IP so that you can block requests you could start by configuring CORS with the Access-Control-Allow-Origin header set to your domain. This will block cross origin access from the browser but isn't a complete fix for what you want.
Configuring CORS

Resources