arm
  • Home
  • Work
  • About
  • Writing
  • Resume
  • Contact
Open to work
← Back to writing
ArchitectureVol. 02 · Issue 02 · 6 min read
Three layers of auth why Next.js middleware alone is not enough.
May 2026 · Parmjeet Mishra

Rentwise has three user roles — Owner, Tenant, Admin. Each role sees a completely different dashboard. Getting this wrong does not just break the UI — it potentially exposes one tenant's data to another. So I took auth seriously.

I started with the obvious approach: Next.js Middleware. Protect the /dashboard routes, redirect unauthenticated users to /login. Done, right?

Wrong. Here is what middleware alone misses — and how I ended up with three layers.

Layer 1: Middleware (the gatekeeper)

Next.js Middleware runs at the edge before the request reaches your page. It is fast, it redirects, and it handles the obvious case: 'is this user logged in at all?'

But here is the problem: Middleware does not protect React Server Components. A Server Component that fetches data does not go through Middleware. If your RSC fetches getPropertiesForOwner(userId) without validating the session server-side, an attacker who bypasses the redirect still gets the data.

Layer 2: Server Component layout (the validator)

Every dashboard layout re-validates the session using Better Auth's auth.api.getSession() on the server. If there is no valid session, it throws — which Next.js catches and redirects to the login page.

This catches the RSC data-fetch gap that Middleware misses. It is slightly slower (one extra DB read per navigation) but the security guarantee is worth it.

Layer 3: React Context (the role enforcer)

The third layer is a client-side SessionProvider that passes the validated session to all child components. Role-specific UI (admin-only buttons, owner-only property creation) is gated behind role checks using this context.

"Belt and suspenders and a third belt. The stakes justify the redundancy."

The real-world bug this caught

During testing, I discovered that Middleware was blocking unauthenticated tenant invite acceptance routes — new tenants could not even reach the sign-up page to accept their invite. The fix was redesigning the middleware matcher to allow public invite paths while still guarding all dashboard routes.

Without Layer 2, this would have been a silent security hole. Because Layer 2 caught it independently, I knew immediately when the fix was incomplete.

Written by Parm

Full-Stack React Developer building SaaS and usuable apps.

Next piece
Building RAG that actually →
Open to work

Have something in mind? Let's make it.

iamparmjeetmishra@gmail.com→
GithubMailLinkedInX/Twitter
arm© 2026 — Made with ♡ by Parm
HomeWorkAboutWritingResumeContact