Always redirect http traffic to https traffic in google app engine nodejs flex environment [duplicate] - node.js

I've followed the answer of this: Redirect from http to https in google cloud but it does not seem to be currently accurate any more. The anchor referenced ( https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml#security ) seems to have been removed but without a note of a replacement.
For reference, I am serving NodeJS over a Google App (flex) Engine. As per the answer I've got in my app.yaml:
handlers:
- url: /.*
script: IGNORED
secure: always
Since HTTPS is obviously terminated before it hits my Express engine (and redirection on there would be useless); how is it currently correctly implemented?
Potentially helpful, I have an external domain attached via the "Custom domains" tab in the console, and there is indeed a SSL certificate configured (so if a user manually goes to https://.com everything is fine)

The flexible environment does not current support handlers in the app.yaml. If you want https:// redirection, you have a few options:
Use helmet to do to HSTS stuff for you, and implement your own initial redirect.
I wrote a happy little library to always forces SSL on all routes for express yes-https
We are considering auto-redirecting all traffic to SSL by default. Do you think that would be a good thing for your apps?

Pulling Justin's yes-https library, I was able to get this to work:
var app = express();
app.use(function(req, res, next){
if (req.host != 'localhost' && req.get('X-Forwarded-Proto') == 'http') {
res.redirect(`https://${req.host}${req.url}`);
return;
}
app.router(req, res, next);
});
At first I thought I had to do that since I was on an appengine subdomain and couldn't use HSTS. Then I learned HSTS works fine for subdomains. :) Regardless, I thought people might want to see what the magic bit to use was if they didn't want to use yes-https for some reason.
Justin, auto-redirecting all traffic to SSL by default sounds great to me. I just spent hours trying to figure out how to do so before I found this post because I was trying to get my app to get Chrome's add to homescreen install banner as per https://developers.google.com/web/fundamentals/engage-and-retain/app-install-banners/.

GCP This should be as easy to just use the gcloud app cli and configure a header (Strict-Transport-Security) or redirect rule. Perhaps the push is to force us to Firebase Hosting instead which is forcing HTTPS already. For a quick solution for Single Page apps (static content) with React, Angular etc, we can use this JS snippet.
It ignores localhost environments. You can change localhost with a host name that you would like to exclude. It then redirects using https as protocol.
if ( location.host.indexOf("localhost") < 0 && location.protocol.toLowerCase() !== "https:"){
const url= `https://${location.host}`;
location.replace(url);
}

Related

How to set up rewrite rule in Azure Web App - Linux

I have an Azure Web App running on linux and i want to set up a rewrite rule for my application. When users visit example.com, i will redirect them to www.example.com.
In windows, it is easier to use web.config but how is it done in Linux ?
On the linux, there is no Apache or Nginx installed but i am wondering how the application is running.
How can i get this done ? Set up a rewrite rule on either Apache or Nginx to affect my Azure Web App running on linux ?
In theory, your needs can be solved in two ways.
For more details, you can read this blogs.
And also can download sample code(ASP.NET Core URL Rewriting Sample)to test it.
The first method:
Re-Writing a URL
Here's how to handle a Rewrite operation in app.Use() middleware:
app.Use(async (context,next) =>
{
var url = context.Request.Path.Value;
// Redirect to an external URL
if (url.Contains("/home/privacy")) // you can use equal
{
context.Response.Redirect("https://markdownmonster.west-wind.com")
//return; // short circuit
}
await next();
});
The second method:
The ASP.NET Core Rewrite Middleware Module
The above two methods are officially provided. The actual test needs to be deployed to Azure for testing. If you have any questions, you can also raise a support ticket for help.

Disable default domain https://[project-id].appspot.com of Node JS on Google App Engine

I have deployed my Node JS app onto Google Cloud App Engine, and I can successfully add my custom domain for my app.
Let say my custom domain is example.com.
Now I can browse my app via example.com & www.example.com, it works as expected. But I find that I can still browse my app through the default domain.
https://[project-id].appspot.com
I want to disable the default domain, is it possible to do that?
You cannot disable that default domain. You would have to write a redirect script. You can test for "appspot" in the request's HTTP_HOST, and test for "AppEngine-Google" in the request's HTTP_USER_AGENT, to determine if it is an internal request.
Also, internal functions, like cron jobs and task queues, run on that domain, so be careful what you do. Task queues will fail given a 301.
After considering GAEfan suggestion, I have made some change on the router logic. If the host name is ended with "appspot.com" and the user agent is included "AppEngine-Google", it will redirect to my custom domain.
router.get('/', function(req, res, next) {
if(req.get("host").endsWith(GOOGLE_APP_SPOT) &&
req.get("User-Agent").includes(GOOGLE_USER_AGENT))
{
var redirectURL = url.format({
protocol: req.protocol,
host: CUSTOM_DOMAIN,
pathname: req.originalUrl
});
res.redirect(redirectURL);
}
res.render('templateName', viewModel);
});
You can do it just using the dispatch.yaml file from App Engine, list all your domains there, but not the *.appspot.com one. Google will show a 404 route when you try to access that.
EDIT: Not possible anymore, check comments.
Checkout the official reference.

HTTP to HTTPS redirection on App Engine Flexible

I've followed the answer of this: Redirect from http to https in google cloud but it does not seem to be currently accurate any more. The anchor referenced ( https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml#security ) seems to have been removed but without a note of a replacement.
For reference, I am serving NodeJS over a Google App (flex) Engine. As per the answer I've got in my app.yaml:
handlers:
- url: /.*
script: IGNORED
secure: always
Since HTTPS is obviously terminated before it hits my Express engine (and redirection on there would be useless); how is it currently correctly implemented?
Potentially helpful, I have an external domain attached via the "Custom domains" tab in the console, and there is indeed a SSL certificate configured (so if a user manually goes to https://.com everything is fine)
The flexible environment does not current support handlers in the app.yaml. If you want https:// redirection, you have a few options:
Use helmet to do to HSTS stuff for you, and implement your own initial redirect.
I wrote a happy little library to always forces SSL on all routes for express yes-https
We are considering auto-redirecting all traffic to SSL by default. Do you think that would be a good thing for your apps?
Pulling Justin's yes-https library, I was able to get this to work:
var app = express();
app.use(function(req, res, next){
if (req.host != 'localhost' && req.get('X-Forwarded-Proto') == 'http') {
res.redirect(`https://${req.host}${req.url}`);
return;
}
app.router(req, res, next);
});
At first I thought I had to do that since I was on an appengine subdomain and couldn't use HSTS. Then I learned HSTS works fine for subdomains. :) Regardless, I thought people might want to see what the magic bit to use was if they didn't want to use yes-https for some reason.
Justin, auto-redirecting all traffic to SSL by default sounds great to me. I just spent hours trying to figure out how to do so before I found this post because I was trying to get my app to get Chrome's add to homescreen install banner as per https://developers.google.com/web/fundamentals/engage-and-retain/app-install-banners/.
GCP This should be as easy to just use the gcloud app cli and configure a header (Strict-Transport-Security) or redirect rule. Perhaps the push is to force us to Firebase Hosting instead which is forcing HTTPS already. For a quick solution for Single Page apps (static content) with React, Angular etc, we can use this JS snippet.
It ignores localhost environments. You can change localhost with a host name that you would like to exclude. It then redirects using https as protocol.
if ( location.host.indexOf("localhost") < 0 && location.protocol.toLowerCase() !== "https:"){
const url= `https://${location.host}`;
location.replace(url);
}

Detecting HTTPS under ExpressJS works only with 1 out of 4 methods

I recently added a SSL certificate to my website. After adding HTTPS support I wanted to redirect people to the secure connection. I googled to see how to detect HTTPS and found on Stack many different ways. It seams they work for others but they don't work for me. Out of 4 ways to check for a secure connection, only one worked.
What doesn't work for me:
req.secure: always return false even if i put manually https://
req.connection.encrypted: always return undefined even if i put manually https://
req.protocol: always return http even if i put manually https://
What works:
req.headers['x-forwarded-proto'] is the only way that actually returns reality.
Knowing this I redirect to a secure connection in the following way:
// Check if the connection is secure, if not, reddiret to a secure one.
function requireHTTPS(req, res, next) {
if(process.env.NODE_ENV == 'production') {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect('https://' + req.get('host') + req.url);
}
}
next();
}
app.use(requireHTTPS);
In any other way that I mentioned above I would get a redirect loop because even after redirecting to HTTPS, the above methods would return false or http.
My question is: why the other methods don't work?
Tech spec:
Website: https://simpe.li
Hosted on Heroku
Node versions: 4.1.1
Express: 4.13.0
Heroku exposes HTTPS for you, but then proxies standard HTTP to your worker. The req.headers['x-forwarded-proto'] method is the correct way to detect HTTPS under Heroku. Similarly, you'll need to access the x-forwarded-for and x-forwarded-port if you need the originating IP address and port.
The Heroku Routing documentation has more details on their routing structure.

Running Keystone.js app over https on Heroku

I have a web app built on Keystone.js CMS for node.js that I will be deploying with a custom domain on Heroku. I want the whole app to run on https by default and not allow any http connections. I've look around quite a bit and can't seem to find a definitive answer as to the best way to go about this. Typically, i.e. for a Rails app, I would just buy a Heroku add-on SSL certificate for my custom domain(s) and point my DNS to point to the Heroku provisioned SSL endpoint. In my app, I would configure to default all connections to HTTPS.
For a node instance (and specifically a Keystone.js instance), I'm a little unclear. Can I just go about the same process as above, buy an SSL add-on and point my DNS to the Heroku SSL endpoint? Do I need to do anything in the base node code to support? And how to enforce https and not allow http?
New to node and keystone and so any help would be greatly appreciated!
Use express-sslify.
I put it in my routes/index.js since the function I export from there receives a reference to the express application.
All you need to do is to tell express to use sslify, but you probably want to not enable it for development.
Since july, Heroku defaults NODE_ENV to production so you can do
// Setup Route Bindings
exports = module.exports = function(app) {
if (process.env.NODE_ENV === 'production') {
var enforce = require('express-sslify');
app.use(enforce.HTTPS({ trustProtoHeader: true }));
}
// Declare your views
};
That will send a 301 to anyone trying to access your app over plain HTTP.

Resources