Karan Kumar
Karan Kumar

Reputation: 3186

Securing the Backend API Endpoints (MERN Application)

I have made a full stack web application using MERN and is deployed using Kubernetes cluster.

The application is runs fine except one issue. And that is, I (as a user), am able to access the API from the browser like www.domain-name/api/orders which gives me the JSON response.

Which I do not want. I need this to be hidden/restricted.

I am using the NGINX-INGRESS for routing as :

apiVersion: extensions/v1beta1
kind: Ingress
metadata: 
    name: ingress-service 
    annotations: 
        kubernetes.io/ingress.class: nginx 
        nginx.ingress.kubernetes.io/use-regex: 'true'
spec: 
    rules: 
        - host: shopify.dev 
          http: 
            paths:
                - path: /api/users/?(.*) 
                  backend: 
                    serviceName: auth-srv 
                    servicePort: 3000
                - path: /api/orders/?(.*)
                  backend: 
                    serviceName: orders-srv
                    servicePort: 3000
                - path: /?(.*) 
                  backend: 
                    serviceName: client-srv
                    servicePort: 3000 

Since both the requests /api and the /* (frontend) are being routed VIA nginx-ingress, is this how this is supposed to work? What is the solution to this?

Upvotes: 2

Views: 810

Answers (1)

Matus Dubrava
Matus Dubrava

Reputation: 14502

Your client app, which is running in the browser, is supposed to be able to fetch the data from the API, therefore it is obvious that whether your app makes the request or you (as a user) make the request from the same browser (or another rest client), it will pass through (assuming the same authentication procedure is followed).

It is impossible to prevent it completely and it should not be required because the user will still have the access to the same data, whether though the app or directly.

But, if you want to hide it because you don't want regular users to see some strange json response when they expect a nice looking frontend app (because they randomly typed an incorrect url? you wouldn't intentionally navigate them to such endpoint in your app), you can implement that logic into your app.

The way you could do that is to include some custom HTTP header in all the request that are made by your fronend app (in axios/fetch calls) and then implement a filtering logic on your backed that will parse this header to see whether the call has been made from the frontend app or directly (possibly a middleware that would redirect the user to root page if it sees a request without this header). I have used this solution before and it works fine.

But again, note that this has nothing to do with security as your data is already available in your frontend app. Also, it has nothing to do with kubernetes itself and any advanced user will be able to forge such request that will bypass this solution. Your data should be protected by authentication, not by some html document.

For example, if you are using axios, you can set up that custom header globally for all request like this (on frontend).

axios.defaults.headers.common['fromApp'] = true 

And on your backend, you can create a middleware

const isFrontendRequest = (req, res, next) => {
  const h = req.get('fromApp') // get the header
  if (!h) {
    // handle the request not originating from your app and return
  }
  next() // custom header was present if we are here, continue normally
}

Which you can then apply globally in front of every incoming request.

app.use(isFrontendRequest)

Upvotes: 7

Related Questions