Skip to content
BuildThenTestedSee packages

Tool changes

Next.js middleware becomes proxy: what it means for your auth checks

Next.js renamed middleware to proxy and says not to rely on it for authorization. What the docs state about Server Actions and page-level checks, and two tests.

Next.js has renamed one of its files, and the rename says something about where authentication checks belong. The middleware file convention is deprecated and is now called proxy. This post covers what the docs say about the new name and why they tell you not to rely on it for authorization. It ends with two checks that matter for any app on Next.js, whether written by hand or by a builder such as v0.

What the docs say

Next.js's documentation, as we read it on 2026-09-21, states that middleware is deprecated and renamed proxy. Proxy runs on every route unless a matcher limits it, defaults to the Node.js runtime, and Server Function calls on excluded paths skip it. The docs say to verify auth inside each Server Function rather than relying on Proxy alone.

Two more statements from the same docs complete the picture. First, an exported Server Action (a function that runs on the server and is called from a form or a button) is reachable via a direct POST request, not just through the UI. Second, a page-level authentication check does not extend to the Server Actions defined within it, and returning null in a layout does not stop nested segments or actions from being reached.

Middleware, for the gloss: a piece of code that runs before a request reaches the page or route it was aimed at. Renaming it proxy describes what it does, which is to sit in front and forward.

Why the rename matters for auth

For a few years, generated Next.js apps commonly had a middleware file that checked for a session cookie and redirected to the login page if it was missing. That still works for the pages it matches. The problem is everything it does not match, and everything that can be called without going through a page at all.

The docs' own list covers it. A Server Action can be called by a direct POST from anywhere, with the action id the browser would have used. Checking the session at the top of a page does nothing for the actions declared further down the same file. A layout that returns null for signed-out users does not stop a nested route from rendering when it is requested directly. Proxy skips Server Function calls on excluded paths.

Each of those is a way to reach a server-side operation while the only check was somewhere else. That is the shape of Authorization enforced only in the browser, extended to the framework layer: the check exists, but not on the path the request took.

The Base44 case in 2025 shows the consequence from the other side. A platform-level flaw let anyone create a verified account on a private app, and Wix fixed it within 24 hours (Wiz Research, 2025). What such an account could do inside any given app depended on whether each action checked permission for itself. The same question applies to every Server Action in a Next.js app.

What to check: sign in as a normal user, open the Network tab, copy a request to a route or action you were never shown, and replay it. Steps: Authorization enforced only in the browser.

What Next.js provides

The framework is not silent on this, and its protections deserve a fair statement. The docs describe encrypted, non-deterministic action ids regenerated per build, removal of unused actions from the client bundle and POST-only invocation. They also describe an Origin to Host header comparison against CSRF (a forged request sent from another site using your logged-in cookies). Marking a module with import 'server-only' causes a build error if it is imported into the browser environment. The authentication guide recommends a server-only Data Access Layer with a session check in every function, returning only the fields a caller needs, and treating Route Handlers like public API endpoints.

The docs also state the limit: these measures reduce risk where an auth layer is missing, but actions must still be treated as public POST endpoints and must check authentication and authorization, including resource ownership. Proxy is described as optimistic checks only, not the sole line of defence.

The other Next.js default to check

While you are in the environment settings, one more default deserves a minute. The docs state that environment variables are only available on the server by default, but that variables prefixed NEXT_PUBLIC_ are inlined into the browser bundle at build time and frozen at that value. A secret stored under that prefix is public. Steps: NEXT_PUBLIC_ prefix on a secret.

Two checks for any Next.js app

  1. Call a Server Action directly. Sign in to an admin test account with the Network tab open and perform an admin-only action, copy the request as cURL, then replay it while signed in as an ordinary user. A success response is the bad result. Full steps: Authorization enforced only in the browser.
  2. Request the admin routes signed out. In a private window, type your app's address followed by /admin, /api/admin and /api/users. A page or data list appearing without a sign-in prompt is the bad result. Full steps: Admin routes without any login check.

Where testing comes in

Next.js did its job: it renamed the file to describe what it does and documented where checks belong. Confirming that every action in your app checks for itself is a separate job. We crawl the built app and the source for every route and Server Action, then request each one signed out, as a normal account and as a second account, including routes no link points to. The Next.js hub lists the patterns we test for on this stack, and the pre-launch package covers them before you ship.

What to do this week

Patterns in this post

  • Authorization enforced only in the browserLogin and permissions

    Anyone who calls the API directly, or edits the page in developer tools, gets the data and actions the screen was hiding.

    Critical
  • NEXT_PUBLIC_ prefix on a secretSecrets and keys

    The build writes the secret's value into public JavaScript, so anyone who loads the site can read it, and a redeploy with the same variable name republishes it.

    Critical
  • Admin routes without any login checkLogin and permissions

    A stranger who types /admin or /api/admin into the address bar can see or change everything the owner can.

    Critical

Questions

does nextjs middleware protect server actions

Not reliably. Next.js's docs state that Server Actions are reachable by direct POST, that a page-level check does not extend to actions defined in it, and that Server Function calls on paths excluded from proxy skip it. Each action needs its own check.

what replaced middleware in nextjs

The middleware file convention is deprecated and renamed proxy. It runs before matched routes and defaults to the Node.js runtime. The docs describe it as optimistic checks only, not the sole line of defence for authorization.

how to test if a server action checks auth

Perform the action in an admin test account with the Network tab open, copy the request as cURL, then replay it while signed in as an ordinary user. A success response means the action did not check who was calling.