skip to Main Content

Let me explain what I want to achieve and what I have tried.

//The Problem
I have an API endpoint built with nextjs
API Url Remote: – http://codingsamadhan.com/api/portfolio
API Url Local – http://localhost:3000/api/portfolio
this is the API for the portfolio items that I want to display on my website, and I did it. but the problem is anyone can request the API, even you can also request the endpoint.

// what I want?
Now this endpoint is publicly accessible, anyone can make GET request, I want to prevent this, I want only my website codingsamadhan.com should make the request, and only those who visit my website can see the portfolio items on my website without login or any session, I don’t want to allow anyone else to call my API endpoint in another place.

// I am thinking
I don’t want to authenticate the API URL using next-auth or JWT because I want to display the items on my website without login just like products, if there is any way to authenticate the endpoint using next-auth or JWT without login please let me know, I don’t know that.

// I have tried
I have tried api-key headers during API calls using the fetch() method, but I realize that the api-key is visible in the network tab of the browser console. so I feel the api-key headers are also meaningless if my api-key is visible to the public.

app/api/portfolio/route.js

export const GET = async (request) => {
  // get api key
  const headersList = headers();
  const apiKey = headersList.get("X-Api-Key");
  const validKey = process.env.API_KEY;

  // check valid api key
  if (validKey === apiKey) {
    await connectDB();
    const portfolioItems = await getPortfolioItems(request); // this function is created in another palce
    return NextResponse.json(portfolioItems);
  } else {
    return NextResponse.json({ message: "Unauthorized Access!" });
  }
};

fetch the api with headers

export const fetchPortfolioItems = async (category, siteName, sort, page) => {
  const response = await fetch(
    `/api/portfolio?siteCategory=${category || ""}&&siteName=${siteName || ""}&&sort=${sort || "latest"}&&page=${page || "1"}&&perPage=${3}`,
    {
      method: "GET",
      headers: {
        "X-Api-Key": "30JmsSQENLRPnpECk25gftymnKUQ9H1SMpQ5k4leFUTw0QgAA8vvH0gkzBV1heEXA7Wv9HK2WspLLPFn8BnSfaBd5xSZLgtk",
      },
    }
  );
  return response.json();
};

the "X-Api-Key" is visible in the network tab in the browser’s console, so this method is useless for me. enter image description here

2

Answers


  1. Maybe try using SSR in your nextjs. First, you will create the webpage with the details on your server then you serve it to the client. With this method, nobody can see what API you are using.

    Server-side Rendering (SSR), Data Fetching

    Login or Signup to reply.
  2. this is where you can use CORS:

    CORS is a security mechanism that enables a server to specify which
    origins are allowed to access and load resources in a web browser. In
    this context, an “origin” refers to the combination of the protocol,
    domain, and port number a request comes from.

    In detail, CORS is a protection system implemented by web browsers to
    enforce restrictions on cross-origin requests. Its main goal is to
    protect user security and prevent unauthorized access to resources and
    data.

    To enforce CORS, browsers and servers exchange a set of specific HTTP
    headers.

    either using next.config.js

    // next.config.js
    const nextConfig = {
        async headers() {
            return [
                {
                    // matching all API routes or SPECIFY YOUR api
                    source: "/api/:path*",
                    headers: [
                        { key: "Access-Control-Allow-Credentials", value: "true" },
                        { key: "Access-Control-Allow-Origin", value: "https://codingsamadhan.com" }, 
                        { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
                        { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
                    ]
                }
            ]
        }
    }
    
    module.exports = nextConfig
    

    Or set headers in middleware:

    import { NextResponse } from "next/server";

    export function middleware() {
    // retrieve the current response
    const res = NextResponse.next()

    // add the CORS headers to the response
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', 'https://codingsamadhan.com') 
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )
    
    return res
    }
    
    // specify the path regex to apply the middleware to
    export const config = {
        matcher: '/api/:path*',
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search