Safeguard
Security Guides•

Next.js Server Actions are public endpoints: check auth inside

A Server Action can be called with a direct POST, so a page level login check does not protect it. Verify authentication and ownership inside every action.

Safeguard Security Team
3 min read

Treat every exported Next.js Server Action as a public POST endpoint. The Next.js data security guide says a page level authentication check does not extend to the actions defined within it, so each action must verify the caller and the resource on its own.

What the docs say

By default, when a Server Action is created and exported, it can be reached with a direct POST request, not only through your UI. An action that is not imported anywhere is still callable from outside, according to the guide.

Next.js adds protections. It creates encrypted, non-deterministic action IDs, and it removes unused actions from the client bundle during the build. The docs are careful to say this reduces risk but does not replace checks: you should still verify authentication and authorization inside each action.

The classic mistake

A page checks the session and redirects non-admins. The page contains a form whose action deletes records. The developer assumes the delete is protected because the page is. It is not. The redirect decides which UI renders. The action is a separate entry point.

async function deleteAll() {
  'use server'
  const session = await auth()
  if (!session?.user?.isAdmin) {
    throw new Error('Unauthorized')
  }
  await db.record.deleteMany()
}

The check inside the action is the one that counts.

Authentication is not authorization

Knowing the user is logged in is only the first question. The guide's example deletes a post: it checks the session, loads the post, and compares post.authorId to the session user before deleting. Skipping the ownership check is how Insecure Direct Object Reference bugs appear, where one user changes an ID and acts on another user's data.

Validate inputs and limit what you return

  • Treat form data, URL parameters, headers and search params as user controlled. The guide shows an anti-pattern that trusts an isAdmin search parameter.
  • Return only what the UI needs. Action return values are serialized and sent to the client, so do not return a raw database record.
  • Consider rate limiting expensive actions such as sending email.

Keep actions thin

The guide suggests a server-only data access layer that performs authentication, authorization and database work, with the action just calling it. Then a new action cannot forget the checks, because they live in the function it must call. See how a data access layer works in Next.js.

Quick check

Does the build removing unused actions make them safe?

It reduces exposure for unused ones. Actions you use are still reachable by POST, so check authentication and authorization inside them.

Is a middleware login check enough for actions?

The docs point to checking inside each action. Do not make a single outer check your only control.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.