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
- 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.
- Request the admin routes signed out. In a private window, type your app's address followed by
/admin,/api/adminand/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
- Replay one admin action from an ordinary account: Authorization enforced only in the browser.
- Try the admin routes signed out: Admin routes without any login check.
- List every
NEXT_PUBLIC_variable: NEXT_PUBLIC_ prefix on a secret.