Skip to content

Recommend protecting auth close to the resource - #3426

Merged
jacekradko merged 50 commits into
mainfrom
jacek/middleware-auth-resource-guidance
Jul 6, 2026
Merged

jacekradko merged 50 commits into
mainfrom
jacek/middleware-auth-resource-guidance

Conversation

@jacekradko

@jacekradko jacekradko commented Jun 8, 2026 •

Copy link
Copy Markdown
Contributor

Stops recommending middleware as the place to gate auth and points protection at the resource that reads the data (the page, Route Handler, Server Action, or endpoint). The copyable createRouteMatcher() + auth.protect() / !isPublicRoute allowlist examples come out of the guides and references; clerkMiddleware() stays documented for its non-auth uses (redirects, headers, geo, route matching).

This began as Next.js-only and now also folds in the Astro, Nuxt, and Core-2 upgrade-guide versions that were open as separate PRs (#3404-3408, now closed). The old pattern survives on purpose in the renamed canonical guide protect-content (was protect-pages), which gains a "migrating from middleware-based auth checks" walkthrough: before/after, the requireUser() / requireAuth() helper, and the add-first-remove-last ordering for inverting !isPublicRoute. That guide and the per-SDK reading.* pages that host the helper are the content worth real review.

The deprecation wording is deliberately uneven and worth checking: Next.js and Astro call createRouteMatcher() "deprecated" because their SDKs log a runtime warning (Astro shipped it in v3.4.8; Next.js ships it in clerk/javascript#8994), while Nuxt only says "no longer recommended" since its SDK hasn't deprecated the helper. Because of the Next.js side, this has to merge together with clerk/javascript#8994, or the docs assert a deprecation that isn't live yet.

One separable rider remains if you'd rather split it: the use-auth reference/partial consolidation.

Reframe middleware-based auth gating as no longer recommended in favor of
checks close to the resource. Adds a shared partial, a 'Migrating from
middleware checks' section to protect-pages, swaps createRouteMatcher
patterns to :path*, and softens the clerk-middleware reference callouts to
'no longer recommended'.
@vercel

vercel Bot commented Jun 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-docs Ready Ready Preview Jul 6, 2026 2:57pm

Request Review

@jacekradko
jacekradko marked this pull request as ready for review June 8, 2026 14:34
@jacekradko
jacekradko requested a review from a team as a code owner June 8, 2026 14:34
Lead with the recommendation (protect access as close to the resource as
possible) instead of demoting middleware gating. Downgrades the callouts from
WARNING to TIP/NOTE, drops the 'no longer recommended'/'wrong layer'/'can fail
to apply' framing, renames the protect-pages section to 'Why protect close to
the resource?', and keeps clerkMiddleware() explicitly supported for non-auth
work.
State plainly that clerkMiddleware() is required and is the right place for
redirects/headers, without 'still'/'remains'/'fully supported' that presuppose
a prior state.
Remove the 'rather than gating in middleware / keeps the check in sync' tail
on the satellite-domains note, strengthen the onboarding callout to a direct
'enforce at the resource' IMPORTANT, and drop 'still' from the sign-in public-route
note.
Drop the 'rather than in your middleware' intro tail, the 'no resource-level
equivalent that is also a security boundary' concession, the 'a layout can
still handle the redirect, but' hedge, the 'no codemod or lint rule yet' line,
and flatten the 'works, but' comparison in the Why section.
…vel protection

Restructure clerk-middleware.mdx: reframe createRouteMatcher() to non-auth
route matching and replace the auth-gating sections (Protect routes, multiple
groups, all routes, token types) with one Protecting routes pointer to
protect-pages / authorization-checks / auth({ acceptsToken }). Drop the
middleware option from basic-rbac, the !isPublicRoute sections from the custom
sign-in/up guides, and repoint the verifying-* token-type links to the route
handler approach.
Jacek added 3 commits June 30, 2026 14:57
…clerk/nextjs #8994); keep middleware-auth-gating as editorial
…uireAuth into reading.astro per Alexis's #3407 direction
@jacekradko jacekradko changed the title Recommend protecting auth close to the resource (Next.js) Recommend protecting auth close to the resource Jun 30, 2026
Jacek added 2 commits July 1, 2026 18:30
…ore-2, session-tasks, mcp, and clerk-middleware notices
- fix incremental flow: narrow middleware patterns per slice instead of removing all checks mid-migration; note double protection is safe
- expand Pages Router warning to cover pages/api handlers and Bulk Fixer non-applicability
- warn manual migrators about the isPublicRoute inversion pattern
- add URL-pattern to folder-glob conversion table (route groups, [locale]) and the silent no-match failure mode
- state deprecation mechanics: behavior unchanged, one-time dev warning, removed next major (per clerk/javascript #8994)
- state ESLint >=9 flat-config prereq and experimental/pin advice
- keep config.matcher in 'after' proxy.ts snippets; point non-auth createRouteMatcher uses at native matching
- protect-content: auth.protect() in a Server Action returns a 401, not a redirect (matches SDK protect.ts)
- app-router/auth: add the Server Action 401 case to the behavior callout
- dedupe auth.protect() behavior sentence and Bulk Fixer description into shared partials
…ion check, astro import + redirect target

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@alexisintech

alexisintech commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Pushed some review fixes directly in 3c51752.

  • Nuxt combined example: scoped the org:invoices:create check to /api/invoices only — the previous shape applied it to /api/admin too, which would block admins who lack invoice permission.
  • Nuxt route matching: added a matchesRoute(path, route) helper (segment-exact or ${route}/ prefix) so /api/admin doesn't collide with /api/administer. Same approach the session-tasks example already uses in this PR.
  • Astro createRouteMatcher() snippet: added the missing import { createRouteMatcher } from '@clerk/astro/server'.
  • reading.astro.mdx: switched the earlier .astro example from /login to /sign-in so it matches the new requireAuth() helper's redirect target.

@alexisintech alexisintech left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alrightyyy I think this is ready to ship 🙏

…ssues

- nuxt clerk-middleware: match on getRequestURL(event).pathname; event.path
  includes the query string, so /api/admin?page=2 bypassed the new
  matchesRoute examples entirely
- build-mcp-server: make shared prose tool-name-neutral (next uses
  get-clerk-user-data, express uses get_clerk_user_data per clerk/mcp-tools);
  fix mark highlight ranges that ran past both code blocks
- reading: add null guards after currentUser() (typed User | null, examples
  failed strict typecheck)
- use-auth/use-user partials: tanstack filename app/routes -> src/routes to
  match the quickstart and same-page examples
- reading.astro: API route filename src/api -> src/pages/api (Astro only
  serves endpoints under src/pages)
- astro clerk-middleware: reword :path* NOTE with framework-neutral rationale
…-resource-guidance

# Conflicts:
#	docs/guides/ai/mcp/build-mcp-server.mdx
…-resource-guidance

# Conflicts:
#	docs/_partials/nextjs/next-steps.mdx
#	docs/getting-started/quickstart.nuxt.mdx
@jacekradko
jacekradko merged commit 65c8d04 into main Jul 6, 2026
8 checks passed
@jacekradko
jacekradko deleted the jacek/middleware-auth-resource-guidance branch July 6, 2026 15:01
SarahSoutoul pushed a commit that referenced this pull request Jul 6, 2026
Co-authored-by: Alexis Aguilar <[email protected]>
Co-authored-by: Fredrik Höglund <[email protected]>

This branch was successfully deployed

1 active deployment
Preview — 3f2d3dc2 Deployed Jul 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants