feat(backend): Add Frontend API proxy helpers#7602
Conversation
…s, and @clerk/express Implement clerkProxy helper that abstracts away the complexity of proxying Clerk's Frontend API (FAPI) requests. This enables scenarios where direct communication with Clerk's API is blocked or needs to go through the application server. - Core proxy implementation in @clerk/backend/src/proxy.ts with environment-aware URL derivation - Next.js integration via clerkMiddleware frontendApiProxy option and route handlers - Express middleware for handling proxy requests with body streaming support - FAPI URL constants added to @clerk/shared for environment detection Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: adaf188 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- Add comprehensive tests for @clerk/backend/proxy including FAPI URL derivation, path matching, and request forwarding - Add tests for @clerk/nextjs/proxy route handlers and exports - Add tests for @clerk/express/proxy middleware and request conversion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Next.js proxy tests mocked the underlying @clerk/backend/proxy, making them essentially test that wrapper A calls function B - no real behavior was verified. The backend proxy tests provide actual coverage. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow the `enabled` option in `frontendApiProxy` to accept a function `(url: URL) => boolean` for conditional proxy based on the request URL. This enables scenarios where an application has multiple domains and only some require proxying (e.g., `foo.replit.app` proxied while `foo.com` uses direct FAPI access). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add X-Forwarded-Host and X-Forwarded-Proto headers for proxy awareness - Preserve existing X-Forwarded-* headers from upstream proxies - Rewrite Location headers for FAPI redirects to go through the proxy - Add tests for new header handling and redirect rewriting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…t.js - Remove separate @clerk/express/proxy entry point and middleware - Embed proxy handling directly in Express clerkMiddleware - Auto-derive proxyUrl from frontendApiProxy config for handshake redirects - Add FrontendApiProxyOptions type with enabled and path options - Align API structure between Express and Next.js SDKs - Remove low-value constant tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change from defaulting enabled to true, to requiring explicit enabled: true - Update tests to use enabled: true - Update JSDoc to remove default annotation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes issue where paths like /__clerk-admin would incorrectly match the /__clerk proxy path. Now requires either an exact match or a trailing slash boundary. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensures that proxy paths like /__clerk/ work correctly by stripping trailing slashes before matching. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…g changeset - Update exports snapshot to include new proxy exports (DEFAULT_PROXY_PATH, clerkFrontendApiProxy, createFrontendApiProxyHandlers) - Fix proxyUrl test assertion to check for falsy value instead of key absence (handleMultiDomainAndProxy always returns proxyUrl: "") - Add changeset for frontend API proxy feature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/nextjs/src/server/index.ts`:
- Around line 78-87: Remove the new barrel re-exports from index.ts: delete the
export block that re-exports clerkFrontendApiProxy,
createFrontendApiProxyHandlers and the types FrontendApiProxyHandlers,
FrontendApiProxyOptions, NextFrontendApiProxyOptions; instead ensure
consumers/importers use the dedicated module path './proxy' directly (or add a
new explicit entrypoint file if needed) and update any internal imports to
reference './proxy' rather than the package root to avoid expanding the barrel
and preventing possible circular dependencies.
- Fix simple-import-sort lint errors in authenticateRequest.ts and utils.ts - Clear authenticateRequestMock between tests to prevent stale call counts from causing `.not.toBeCalled()` assertions to fail in proxy tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@packages/express/src/authenticateRequest.ts`:
- Around line 132-136: The proxy path check in authenticateRequest.ts fails when
request.originalUrl contains a query string; update the proxy matching logic to
extract only the pathname (strip the query string) from request.originalUrl ||
request.url before comparing to proxyPath. In practice, compute a
requestPathName (or reuse request.path) that excludes the query string, then use
that value in the existing if checks that reference proxyEnabled, requestPath
(or requestPathName) and proxyPath (including the startsWith(proxyPath + '/')
check).
- Around line 176-188: The code that auto-derives proxyUrl when proxyEnabled and
!options.proxyUrl uses request.headers['x-forwarded-proto'] and
request.headers['x-forwarded-host'] directly, which fails for comma-separated
header chains; update the extraction in the resolvedOptions block (around
proxyEnabled, options.proxyUrl, resolvedOptions, derivedProxyUrl, proxyPath) to
split the header value on ',' and take the first item, trimming whitespace (e.g.
const protoHeader = Array.isArray(forwardedProto) ? forwardedProto[0] :
forwardedProto; const protoValue = (protoHeader || '').split(',')[0].trim(); and
same for host) before computing protocol, host and derivedProxyUrl so the first
forwarded value is used.
…aders Split header values on ',' and take the first item to handle multi-proxy chains (e.g. "https, http" or "app.example.com, proxy.example.com"). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
request.originalUrl includes query parameters, causing proxy path matching to fail for requests like /__clerk?_clerk_js_version=5.0.0. Parse the URL to extract pathname before comparing, consistent with the backend's matchProxyPath implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| * Removes trailing slashes from a string without using regex | ||
| * to avoid potential ReDoS concerns flagged by security scanners. | ||
| */ | ||
| function stripTrailingSlashes(str: string): string { |
There was a problem hiding this comment.
[nit] I think this might be duped
packages/express/src/types.ts
Outdated
| * Enable Frontend API proxy handling. When true, requests to the proxy path | ||
| * will be proxied to Clerk's Frontend API and the proxyUrl will be auto-derived. | ||
| */ | ||
| enabled?: boolean; |
There was a problem hiding this comment.
[nit] I think it would make sense to make this a required configuration value so it's easy to grok if the feature is on or off
There was a problem hiding this comment.
@jacekradko required if frontendApiProxy is present right?
| '@clerk/backend': minor | ||
| '@clerk/nextjs': minor | ||
| '@clerk/express': minor | ||
| --- |
There was a problem hiding this comment.
| --- | |
| '@clerk/shared': minor | |
| --- |
- Remove duplicate stripTrailingSlashes from express, import from backend - Make FrontendApiProxyOptions.enabled required for clarity - Add @clerk/shared to changeset Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accept `boolean | ShouldProxyFn` for the enabled field, matching the Next.js interface. The function form receives the request URL and allows per-request proxy decisions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the new built-in Frontend API proxy support added to clerkMiddleware for Next.js and Express. Updates the proxy guide with simplified setup examples and adds reference documentation for the new option, including multi-domain support and App Router route handler helpers. Impl: clerk/javascript#7602 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…elper # Conflicts: # packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Description
Adds Frontend API proxy support to
clerkMiddlewarefor both Next.js and Express. This enables scenarios where direct communication with Clerk's API is blocked or needs to go through the application server.API
Next.js
Express
Key Features
clerkMiddlewareproxyUrlfor handshake redirects is automatically derived from thefrontendApiProxyconfigenabledto conditionally enable proxy based on request URLType of change
Testing
Summary by CodeRabbit
New Features
Behavior
Tests
Documentation