diff --git a/.changeset/soft-astro-routes.md b/.changeset/soft-astro-routes.md new file mode 100644 index 00000000000..8948baf30b7 --- /dev/null +++ b/.changeset/soft-astro-routes.md @@ -0,0 +1,21 @@ +--- +'@clerk/astro': patch +--- + +Deprecate `createRouteMatcher()` in favor of resource-based auth checks. + +Instead of protecting routes only from middleware, move auth checks into each protected Astro page, API route, or server-side handler: + +```ts +import type { APIRoute } from 'astro'; + +export const GET: APIRoute = ({ locals }) => { + const { userId } = locals.auth(); + + if (!userId) { + return new Response('Unauthorized', { status: 401 }); + } + + return Response.json({ userId }); +}; +``` diff --git a/packages/astro/src/server/route-matcher.ts b/packages/astro/src/server/route-matcher.ts index 85987b500aa..58116a8929e 100644 --- a/packages/astro/src/server/route-matcher.ts +++ b/packages/astro/src/server/route-matcher.ts @@ -1,3 +1,4 @@ +import { deprecated } from '@clerk/shared/deprecated'; import { createPathMatcher, type PathMatcherParam } from '@clerk/shared/pathMatcher'; export type RouteMatcherParam = PathMatcherParam; @@ -9,8 +10,34 @@ export type RouteMatcherParam = PathMatcherParam; * You can use glob patterns to match multiple routes or a function to match against the request object. * Path patterns and regular expressions are supported, for example: `['/foo', '/bar(.*)'] or `[/^\/foo\/.*$/]` * For more information, see: https://clerk.com/docs + * + * @deprecated This function will be removed in the next major version. Use resource-based auth checks instead. + * Move auth checks into each Astro page, API route, or server-side handler that accesses protected data. + * Middleware-based auth checks rely on path matching, which can diverge from how Astro routes requests and + * leave protected resources reachable. + * + * Instead of protecting routes only from middleware, protect the resource itself: + * + * ```ts + * import type { APIRoute } from 'astro'; + * + * export const GET: APIRoute = ({ locals }) => { + * const { userId } = locals.auth(); + * + * if (!userId) { + * return new Response('Unauthorized', { status: 401 }); + * } + * + * return Response.json({ userId }); + * }; + * ``` */ export const createRouteMatcher = (routes: RouteMatcherParam) => { + deprecated( + 'createRouteMatcher', + 'Use resource-based auth checks instead. Move auth checks into each Astro page, API route, or server-side handler that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Astro routes requests and leave protected resources reachable.', + ); + const matcher = createPathMatcher(routes); return (req: Request) => matcher(new URL(req.url).pathname); };