Simple password-protection for React app on Heroku - reactjs

I have a simple React app, created with create-react-app, that I'd like to deploy to Heroku (or somewhere easy) and password-protect. The protection can be really simple—just a single password is fine.
I started looking into HTTP basic auth but didn't find an easy answer. The closest I found was in this post, but (a) I don't love the idea of having to eject my app, and (b) I couldn't get it working. I was hoping I could find a Heroku plugin, but no luck there either.
It wouldn't be too hard to write a component that wraps my app and requests a password before showing it. The problem is that it executes client-side. I want to store the correct password server-side (or a hash thereof), and have the app send password attempts up to the server.
Since create-react-app operates on top of Node, I'm hoping there's an easy way to tell it to execute and store certain things on the server, but maybe I'm wrong. Any suggestions?

This create-react-app buildpack seems to support http basic auth:
https://github.com/substantial/create-react-app-buildpack
https://elements.heroku.com/buildpacks/substantial/heroku-buildpack-static

I am assuming your intentions are wanting to protect the config vars in heroku so other people cannot access you database with your credentials.
The way I password protected my deployment to heroku, is to make a keys_prod.js file containing the Heroku config vars of my mLab database in my backend using express and mongoDB:
keys_prod.js file:
module.exports = {
mongoURI: process.env.MONGO_URI,
secretOrKey: process.env.SECRET_OR_KEY
};
keys.js file:
if (process.env.NODE_ENV === 'production') {
module.exports = require('./keys_prod');
} else {
module.exports = require('./keys_dev');
}
in my server.js file I added:
// DB Config
const db = require('./config/keys').mongoURI;
// Server static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
This allows you to request the config vars you filled in heroku without including it in your repo.

If you use Node in backend you can use Passport Basic Auth
app.get('*', passport.authenticate('basic', { session: false }), (req, res) => {
res.sendFile(path.join(`${__dirname}/../build/index.html`))
})
Every time you access the page in browser, a popup will appear, asking you username and password.

Related

Page reload or pasting url gives 404 with MERN stack

I am building a simple website that uses MERN stack running on apache.
There is a proxy (& reverse proxy) settings on /api to route to ip:port/api
At some point in the last couple of months, any page refresh or pasting urls causes a 404. I cannot identify what causes this.
It is using client side routing (based and it was working. It is still working on localhost only breaks on the server.
Now when I put the old code that used to work on the server, it breaks the same way. This suggests that a change in the environment is causing/contributing.
One developer I was working added this piece of code to try to address it.
if (process.env.NODE_ENV === "production") {
// Set static folder
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
It doesn't seem to have any effect even if I remove the if condition. I did a little test.
I added an image with name 'register'
If I go to my website and click on register it works
If I visit domain/register, it is showing the image, so even with the code snippet above it is treating it as a request for static file and not letting it pass on and resolve to the index.html
About the server
Ubuntu with Apache with proxy on /api to node server
Uses a self signed certificate but it breaks on http or https.
This seems to be a common problem. If anyone has seen this before or can give pointers on where to debug this, I would appreciate it.
Trying this code worked for me. And refer this for the difference between path.resolve and path.join
if (process.env.NODE_ENV === 'production') {
const root = path.join(__dirname, 'client', 'build');
app.use(express.static(root));
app.get('*', (req, res) => {
res.sendFile('index.html', { root });
})
}

How to connect frontend to json data on heroku

I'm trying to deploy my first React app on Heroku. I used simple json files for the backend.
Locally, everything runs good: my server is on localhost:8080, and frontend axios calls gets data from it like so:
axios.get(localhost:8080/bench).then( (response) => {
// my logic here
})
My deployment flow is:
to run a npm build and put everything in the build folder into the server end's public folder. Here's the entry-point file:
const path = require("path");
const publicPath = path.join(__dirname, "public");
console.log(publicPath);
app.use(express.static(publicPath));
app.get("*", (req, res) => {
res.sendFile(path.join(publicPath, "index.html"));
});
push to build artifacts to Heroku
Doing so, everything from the frontend part runs good on Heroku.
My concern is that I can't figure out what axios calls I should use for the frontend to get the data from the server. Is there anything I am missing?
Localhost only works on your machine. In your frontend, you'll need to change the axios url to point to the URL of your deployed server like so:
axios.get(`${YOUR_HEROKU_URL}`/bench)

How do I configure my React-Node App so I can deploy it to Heroku?

So I've built a simple MERN app using create-react-app, that I want to deploy to Heroku. I build the front end in a client folder operating on localhost:3000, that sends requests to my express sever as a proxy to localhost:5000. My file structure is as follows:
+client
|
+-node_modules
+-public
+-src
|
+-components
+-App.js
+-index.js
//server
+-models
+-node-modules
+-package-lock.json
+-package.json
+-server.js
And I've set up the proxy in my package-json like this: "proxy": "http://localhost:5000",
So my main question is this: How do I configure my API endpoints for deployment?
At the moment, they're structured like this:
API call from react component:
useEffect(() => {
axios.get("http://localhost:5000/api/all-cafes")
.then((cafe) => {
setCafe(cafe.data);
})
.catch((err) => {
console.log(err);
})
}, [])
Express function on server.js
app.get('/api/all-cafes', (req,res) => {
Cafe.find()
.then((result) => {
res.send(result)
})
.catch(err => {
console.log(err)
})
})
My other question is what is the role of the .env file, and will I need to make one in order to solve this?
I've had a helpful suggestion saying that I can run the front end and back end on different servers, and adjust the code depending on whether it is in development or production, using the following code:
const prefix = process.env.NODE_ENV === 'production' ? "http://heroku_app_address" : "http://localhost:5000"
function getUrl(relativeUrl) {
return prefix + "/" + relativeUrl;
}
fetch(getUrl('api/all-reviews'));
But I'm not sure how to implement this, whether I need a .env file, and if so, what to put in said file.
The .env file helps you specifiy certain credentials or endpoints that are either going to change based on deployment environment (dev,qa,prod may have differewnt API endpoints), or you want to provide certain secret keys or configurations, which otherwise should not be part of your code repository (clientSecret etc).
The create-react-app.dev/docs has detailed explanation to these.
If you have not bootstraped your app using create-react-app then you can use dot-env npm package. The steps are detailed here: Stack overflow :Adding an .env file to React Project

how to deploy an express/react to apache

I have a project that has a react app inside the express server. I would like to deploy it to my own CentOS/Apache server. How i can i do this? I've done some google and seen AWS things, and i just doesn't seem like it needs to be that complicated. I really just want it to run on my server so i can show other people and do testing. I do have a spare computer to create another nginx server if needed (or whatever else you guys reccomend).
Ive also added this code to my server.js file. which aparently isnt enough. Thanks for all help!
if(process.env.NODE_ENV === 'production'){
//SET STATIC FOLDER
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(_dirname, 'client', 'build', 'index.html'));
})
}

After deploying React/Express app to Heroku unable to start passport.js flow (page reloads instead) [duplicate]

I'm building a node + express server, with create-react-app to the frontend.
I used passportjs for auth routes handling, and all the stuff totally working on localhost ( backend on port 5000 and frontend on port 3000, with a proxy ).
When I deploy to Heroku, seems like the server can't recognize my auth routes and so heroku serve up static index.html.
If I test my APIs with Postman all seems to work ( I can see the html page for google oauth ), but with an anchor tag in my react app or manually writing the endpoint in the url, I can see only the same page reloading.
My server index.js:
const express = require('express')
const passport = require('passport')
const mongoose = require('mongoose')
const path = require('path')
// KEYS
const keys = require('./config/keys')
// MONGOOSE MODELS
require('./models/User')
mongoose.connect(keys.mongoURI)
// PASSPORT SETUP
require('./config/passport')
// CREATE THE SERVER
const app = express()
// EXTERNAL MIDDLEWARES
require('./middlewares/external')(app)
// ROUTE HANDLERS
require('./routes/authRoutes')(app)
// PRODUCTION SETUP
if (process.env.NODE_ENV === 'production') {
// express serve up production assets ( main.js, main.css )
app.use(express.static('client/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
// START THE SERVER
const PORT = process.env.PORT || 5000
app.listen(PORT)
Flow:
LOCALHOST:
react app starts -> I click 'Google Login' -> GET request to "/auth/google" -> google oauth flow -> redirect to "/" and my react app reappears, the user is logged in.
HEROKU:
react app on my-app.herokuapp.com/ -> click on "Google Login" -> the page reloads, nothing happens. the user is not logged in.
Please guys, help me.
Thanks
This is a result of the service worker being installed by default to make your app a Progressive Web App
To determine if this is an issue for you, test your heroku production mode app in incognito mode. The request for /auth/google should now reach the server and behave as it does in development.
Once you determine it is an issue, you can remove the
import registerServiceWorker from "./registerServiceWorker";
from your /client/src/index.js file.
You browser cache may already contain an installed service worker so you may have to
clear browser cache on a user browsers
uninstall the server worker programmatically
import { unregister } from './registerServiceWorker';
....
unregister();
I had the same issues with same symptoms exactly.
For me the cause was a typo in the keys: in server/config/prod.js I had a line reading cookieKey: process.env.COOKIE_KEY but in Heroku Config Variables that variable was named cookieKey. Renaming it to COOKIE_KEY inside Heroku solved the issue.
If you've followed the Stephen Grider tutorial one thing I'm wondering: Is your passport.js file in config or services? I see you've written in index.js: require('./config/passport')
whereas mine in index.js is require('./services/passport')
may not be your solution to the google oauth flow hanging in production but may help.

Resources