Next.js Discord

Discord Forum

Securing API Routes

Unanswered
Northeast Congo Lion posted this in #help-forum
Open in Discord
Northeast Congo LionOP
I am using NextJS app router with nextauth/authjs

Within this app are api routes (obviously) some of them are open all the time because pages that can be viewed without logging in definitely need those. I'm calling these public api routes

Then some are only available to logged in users. Things like created/editing/deleting records. I'm going to call these protected api routes.

And then I imagine there are some that the server only calls it self. I'll call these private api routes.

how are developers usually setting these up so they are only accessible by properly authorized/authenticated entities?

lets say there is a data model called Products. a product page is probably public by default because you dont need an account just to view a product. so the api call that gets a list of products to then build a react page is probably public.

But if you want to edit a product you would need to be authenticated. So that route must be protected.

What is the most common way this is setup.??

I had assumed early on that i'd just use middleware but that would protect the route to it, so i'd need separate route paths for protected/private. OR a very big switch statement in middleware checking all routes/methods to see what to allow or not. This would require api/public/products route and an api/protected/products route, but seems weird to maintain like that for some methods being okay (get) and others protected (post/delete/patch/etc). Two separate paths both with Product (or whatever) models seems odd.

Or I skip middleware and the first thing that is in every single api method handler would need to call a check to authenticate/authorization. This keeps it a single api/products route but that seems to be a ton of duplicate code checking authorization constantly.

Whats best practice here?

1 Reply

Black carp
i'm not sure there is a best practice. but I would recommend going to good ol functional programming in javascript!

you could make a base promise that does the getCurrentUser type of call and does role checks, etc and then continues if allowed. you could also just have a first line of each route const currentUser = await authOr401() type of thing.

I have done it where I make a protectedRoute function that returns a route so it'd be like export const PUT = protectedRoute(async (request.....) => {}); but that can get hard when you want to do multiple "checks" like authentication, authorization, etc...

I tend to skip the middleware for this type of stuff because of my use-cases... but mileage may vary!