0

I want to force https connections for my React app deployed on Google App Engine node.js flexible environment. My React app was created with

npx create-react-app my-cool-app 

And I have an app.yaml placed in project root directory. The app.yaml contains the following:

env: flex runtime: nodejs service: frontend-staging 

I have seen other questions/answers on here mention using the npm helmet library. But I don't understand how that applies to my case. Isn't Google App Engine serving a static build directory using nginx? There is no Express server here - just front end code. How can I set http security headers using this library if I just have front end code? Do I need to place an Express app server in between nginx and my React stuff?

Also I asked Google Support about modifying the nginx.conf file. But, according to them, I would have to SSH into the instance and modify the file that way. Well, what happens if the load on an instance increases and GAE automatically fires up another instance? Now I have to somehow detect that and manually SSH into that instance to fix the nginx.conf file? I saw that mentioned as a potential solution on here as well but this seems like a poor option.

Note: I don't think this is a duplicate. I am specifically asking how to implement the helmet library with nginx + Express + React + code examples for GAE node.js flex environment, not a higher level strategy question.

5
  • having the exact same issue. I have a React app on flex, and a Node API server, also on flex. Getting a redirect to HTTPS has been WAY harder than it should be... anyway, following. Commented Jan 20, 2020 at 2:02
  • @RyanRebo I heard back from google support today, hopefully should have a small hello world example ready in a couple more business days. If no one answers before then I'll post my findings here Commented Jan 21, 2020 at 1:49
  • Cool. I've had zero luck handling it within the app so I'm handling it via a load balancer. Will be interested in seeing if it works for you Commented Jan 21, 2020 at 12:01
  • @RyanRebo finally heard back from Google. Basically you need to fire up an express app server and have it serve your React app build directory. I plan on tackling this next week, once I get it working I'll post an answer here. The full layout looks more or less like this: User Computer -> Internet -> GAE Load Balancer -> AE Instance -> nginx web server -> express app server -> static react files. I'm not sure thats 100% accurate but it should be accurate enough to understand what is going on here, and get the job done. Commented Jan 25, 2020 at 1:25
  • TL;DR: Insert an express app server in between nginx and react. Use express to set the HSTS headers Commented Jan 25, 2020 at 1:27

1 Answer 1

2

I finally figured this out on my own. You need to create an express server, run a "yarn build", and serve those static files generated by the "yarn build" script from the express server. So, I recommend configuring your directory structure like this:

appRoot ->client ->create-react-app contents here app.yaml app.js package.json 

Note that there are TWO package.json's in this config. One is inside the client folder, and is created as part of the setup when you run "create-react-app". The other is for your nodejs server application, and lives in the appRoot directory. Inside the app.js file is where you will place the code to serve your static React files:

const express = require('express'); const helmet = require('helmet') const app = express(); const port = process.env.PORT || 3000; const sixtyDaysInSeconds = 5184000 app.use(helmet.hsts({ maxAge: sixtyDaysInSeconds })) //Serve up all of our static assets app.use( express.static('client/build') ); //Make all incoming GET requests return the index.html in order to take advantage of the client side router app.get('/*', function(req, res) { res.sendFile(__dirname + '/client/build/index.html', function(err) { if (err) { res.status(500).send(err); } }) }) app.listen(port, () => console.log(`Example app listening on port ${port}!`)); 

Make sure you add the "helmet" library to your dependencies by running

yarn add helmet 

And of course add express by running

yarn add express 

All your app.yaml needs to have is:

env: flex runtime: nodejs service: frontend-staging 

Now deploy your app to GAE and you should be serving the HSTS headers along with every request. Note that serving HSTS headers does not redirect a user to https right away. From Mozilla Developer Network, "The first time your site is accessed using HTTPS and it returns the Strict-Transport-Security header, the browser records this information, so that future attempts to load the site using HTTP will automatically use HTTPS instead."

In other words, your user must attempt to access the site at least once using https in order for the HSTS header to be sent.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.