DEV Community


Posted on • Updated on

How to protect NextJS API routes from other browsers/servers

So you have any API routes that you don't want anything to access other than the UI (main website) itself, and you don't want to keep writing if statements on every single one of your API routes. What's the solution?

Writing middleware

Let's create a folder called middleware in our NextJS project and under it create a file called protectAPI.js.

const protectAPI = (handler) => {
    return async (req, res) => {
        if(new URL(req.headers.referer).origin !== '') {
            return res.status(403).json({success: false, message: `Forbidden`})
        return handler(req, res)

export default protectAPI;
Enter fullscreen mode Exit fullscreen mode

Now let's see what's going on here. First of course we define the function protectAPI. We return an asynchronous function which has our req and res.

Now we check the domain that's sending a request with req.headers.referer and seeing if it's not our domain name, return the 403 code and a Forbidden message.

Using this middleware

So we have an API file which is under /api/hello.js. How do we protect it?

import protectAPI from '../../middleware/protectAPI';

const handler = (req, res) => {
    return res.status(200).json({message: 'Hello world!'})

export default protectAPI(handler);
Enter fullscreen mode Exit fullscreen mode

We import the protectAPI function that we wrote before, and then write our API function which in this case is called handler.

At the end we export it by wrapping the handler function with our protectAPI function.


And there you go! Now no domain/browser outside of your own domain can make any requests to /api/hello.

I hope this helped you 😀

Discussion (4)

zakiazfar profile image
Mohd Ahmad

use CORS

a7u profile image
A7U Author

If I'm not wrong, CORS only protects the browser from being accessed from other browsers but not from servers.

andreidascalu profile image
Andrei Dascalu

true that, but then again the example is also (at best) incomplete.

A server does not declare an origin, a browser will do that (also complete with scheme, as an URL). At best, origin check against a server side will reveal the IP and that's about it.

The server-side request will not provide a scheme as origin.

On a more general note, hardcoding anything like this in the application will obviously limit the portability of an API (if you later deploy your frontend on a different URL and you hardcode scheme and domain, you'll need to redeploy your API with an updated check, or at least introduce a runtime config option).

More sensibly would be to delegate this responsibility to a load balancer.

Thread Thread
a7u profile image
A7U Author

True. But I have hardcoded in the post just to give an example, in my app it's not hardcoded but in a config.json called "base_url" which can be changed from the UI.

I think both the example I have given and CORS would be good, because it's never too much for security 😀