15 September 2023
We all get to a point sometime in our software developer career, where we end up with a backend API that is running on some random test server. In most cases these APIs were made available to us with no SSL security certificates for the host. In another example, we integrate to an API that we do not have control over, with a supplied https url with again no valid certificate.
Typically, when testing out of the dev environment, it is not a problem. Some warnings here and there that you can probably ignore (if you are really, really sure).
One of the issues that arrise, is when you deploy a frontend to a valid hosting service (Firebase, AWS, Heroku etc.) for testing, but the frontend still connects to your unsecure backend API. Most browsers, and mobile OSs will block traffic to these APIs and you end up in all kinds difficult issues trying to test.
Should you be in this position where you do not have control to either install your backend API on a secure host/system, or if it is not your API - there is a solution!
Below is a example of setting up a man-in-the-middle SSL secure type API, which will be used to route traffic to and from your unsecured API.
We will use Javascript to create the app, and use Firebase functions to implement this serverless application.
Follow the steps below to install Firebase and get your proxy up and running!
1 - Install the Firebase CLI, or if already installed make sure it is up to date
2 - Create a new folder for this proxy and change into the directory with below steps:
mkdir secure-proxy
cd secure-proxy
3 - Initialise cloud functions, by using the following command:
firebase init functions
Follow the prompts, I have chosen the following:
- New Project
- Functions language: Javascript
- Use ESLint: No
- Install dependancies: Yes
below is a sample output:
You now have a valid functions project setup, now we will create the proxy.
4 - Change into the functions folder:
cd functions
Here you will see the index.js file along with the standard node type setup (node_modules, package.json)
5 - Install needed packages: express, cors, http-proxy-middleware and body-parser
npm install express
npm install cors
npm install http-proxy-middleware
npm install body-parser
Once done, you should have all the dependencies used in the proxy
6 - Edit the index.js file, and paste the following code:
const functions = require("firebase-functions");
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const bodyParser = require('body-parser');
const app = express();
const PORT = process.env.PORT | 5000;
const API_BASE_URL = 'API_BASE_URL';
const cors = require('cors')({origin: true});
app.use(cors);
//a comment
app.use(
'/',
createProxyMiddleware({
target: API_BASE_URL,
changeOrigin: true,
secure: false, // Set to false to allow connections with invalid SSL certificates
onProxyReq: (proxyReq, req, res) => {
// Add CORS headers to the backend's response
if (req.body) {
const bodyData = JSON.stringify(req.body);
// Update header for the proxy request
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
// Write the body data to the proxy request
proxyReq.write(bodyData);
}
},
onProxyRes: (proxyRes) => {
// Add CORS headers to the backend's response
proxyRes.headers['Access-Control-Allow-Origin'] = '*';
proxyRes.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS';
proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization';
},
})
);
exports.app = functions.https.onRequest(app);
Remember to update the API BASE URL to your actual backend API.
7 - Now we can go ahead and deploy our function to FireBase by executing the following command (please make sure your FireBase project is set to the Blaze or higher payment plan):
firebase deploy --only functions,hosting
Once deployment has complete, you should see the result as per below sample:
And that is it! You now have a secure URL that will route all communications to your normal unsecured API.
Remember to only use this in test cases where security is a non-issue during testing, as all communication between the proxy function and your API is readable and unsecure!