Clerk: sessions, redirects and webhooks
The Clerk helpers sit in front of the router, so the rules about what they let through are part of your deployment.
The Clerk helpers sit in front of the router, so the rules about what they let through are part of your deployment. The Clerk guide has the full list; these are the parts that change what you write or run. They replace the "Clerk route rules" and "Clerk webhooks" lines of the internal audit above.
- Protect sections with the matcher, not with text.
createRouteMatchercompares the spelling the router serves a page under: segments decoded once, ASCII case folded, one trailing slash ignored./DASHBOARDand/%64ashboardare the dashboard,/tasks%2F7is not/tasks/7. A rule written aspathname.split("/")[1] === "dashboard"misses the first two. If your router is case-sensitive, pass{ caseSensitive: true }./dashboard/*does not cover/dashboard; write/dashboard(.*). PreferclerkMiddleware({ protect }), which also checksevent.urlafter a rewrite. - A pending session is signed out. A user who has not finished the sign-in tasks Clerk requires has no
userId, andrequireAuthandprotecttreat the request as signed out. - Handshakes go to Clerk and nowhere else. The redirect is sent only to the frontend API of your publishable key, and
only for a return origin in
authorizedParties. SetauthorizedPartiesto a list in every environment, and make your proxy setX-Forwarded-HostandX-Forwarded-Protoitself instead of passing the client's. The development-instance redirect to a__clerk_redirect_urlof the request's choosing, which carried the dev-browser token, is refused. authorizedParties: []is an error. Use a list, orfalseto accept any application of the instance.- Set
jwtKey. Without it a request with a made-upkidmakes the server call Clerk before the signature is checked. There is a limit (4 unknownkids per minute), butjwtKeyremoves the call. Rate-limit requests that carry__clerk_handshake_nonceat the edge: each one costs a call to Clerk. - Webhooks.
verifyWebhooksigns the raw bytes, reads at most 16 signatures, throws on atoleranceSecondsormaxBodyBytesthat is not a finite number, and drops__proto__andconstructor.prototypekeys from the event. A request that verified verifies again inside the tolerance (300 seconds): deduplicate bysvix-id. - The browser side.
HandleSSOCallbackwith its default navigation follows only destinations on the page's origin;clerkJSUrlandclerkUIUrlmust be https (http for localhost); the publishable key and those URLs are configuration, never request data.