Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node JS : Allow only server side calls to my api

I have been racking my brains for a simple solution. Lets say, I have 10 API endpoints in my Node JS application.

I have already allowed 3 of them to be public, the remaining 4 have JWT based authentication

Now I have 3 more routes, which will not have JWT and I need to only allow Server side calls. No browser or curl or postman, should be able to call them. How do I identify from the request object that it is originating from a server?

Or to put it in another way, how to I reject all cross origin calls to my api? As server side does not fall in CORS, they should filter through

----- EDIT -----

I recently came across a service that uses User Agent header to block server side calls. Can i enforce User Agent header for my service and ensure that the header does not have browser agents. This can be hoodwinked easily, but as a theoretical solution, what would be the nodejs interceptor that discards requests whose user agent refers to a browser agent?

like image 209
Sahil Ali Avatar asked Feb 03 '23 22:02

Sahil Ali


2 Answers

You should use a similar authentication/authorization as for the routes that have JWT authentication from the clients.

This means that the caller service should also authenticate using a JWT token, having a special role of service or something like that (this is 100% your decision on what convention you choose). That token should be signed by the caller and verified by the receiving microservice.

This solution has the advantage that it does not depends on the infrastructure, it works the same no matter where the services are deployed.

like image 30
Constantin Galbenu Avatar answered Feb 06 '23 14:02

Constantin Galbenu


You can use the express-ipfilter package and only apply it to certain routes you want to protect:

const express = require('express'),
      ipfilter = require('express-ipfilter').IpFilter;

// Whitelist the following IPs
const ips = ['127.0.0.1'];

// Create the route
app.get("/securePath", ipfilter(ips, {mode: 'allow'}), (req, res) => {
  // only requests from 127.0.0.1 (localhost/loopback) can get here
});

app.get("/openPath", (req, res) => {
  // all requests can get here
});

app.listen(3000);

If you are using Node behind a proxy, you may need to configure the proxy to set a header with the actual IP and then pass the ipfilter function a function in the detectIp property to the second parameter.

Let's say you are using nginx and have it configured to send the original IP through the x-Real-IP header, you can pass this function to ipfilter:

const express = require('express'),
  ipfilter = require('express-ipfilter').IpFilter,
  ips = ['127.0.0.1'];

app.get("/securePath", ipfilter(ips, {mode: 'allow', detectIp: getIp}), (req, res) => {
  // only requests from 127.0.0.1 (localhost/loopback) that go through the proxy can get here.
});

app.get("/openPath", (req, res) => {
  // all requests can get here
});

app.listen(3000);

function getIp(req) { return req.headers["X-Real-IP"] }
like image 109
Luca Kiebel Avatar answered Feb 06 '23 15:02

Luca Kiebel