-
Notifications
You must be signed in to change notification settings - Fork 436
feat(backend): Add Frontend API proxy helpers #7602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
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: f6f4ab3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 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. 1 Skipped Deployment
|
- 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>
Replaces /\/+$/ regex with a simple while loop to avoid ReDoS concerns flagged by GitHub Advanced Security code scanning. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Frontend API proxy feature across the monorepo: new backend proxy module (packages/backend/src/proxy.ts) with public exports and build/package manifests; new shared constants and types (DEFAULT_PROXY_PATH, LOCAL/STAGING/PROD_FAPI_URL, ShouldProxyFn); tsup and package.json updated to publish proxy artifacts; integration into Express and Next.js middleware with a request-to-Request conversion helper and auto-derivation of proxyUrl; Next.js App Router proxy handlers and re-exports; comprehensive unit tests and a changeset. 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/nextjs/src/proxy.ts`:
- Around line 66-72: The interface FrontendApiProxyHandlers is missing an
OPTIONS handler which will break CORS preflight requests; add an OPTIONS:
RouteHandler entry to the FrontendApiProxyHandlers interface and update
createFrontendApiProxyHandlers to include and return an OPTIONS handler that
forwards preflight requests (responds appropriately or proxies the OPTIONS
request to the upstream FAPI) so Next.js can handle CORS preflights—modify both
the FrontendApiProxyHandlers type and the createFrontendApiProxyHandlers
function to include the OPTIONS symbol consistently.
| export interface FrontendApiProxyHandlers { | ||
| GET: RouteHandler; | ||
| POST: RouteHandler; | ||
| PUT: RouteHandler; | ||
| DELETE: RouteHandler; | ||
| PATCH: RouteHandler; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing OPTIONS handler may break CORS preflight requests.
The FrontendApiProxyHandlers interface lacks an OPTIONS handler. If Clerk's FAPI responds to CORS preflight requests, clients making cross-origin requests to the proxy will fail because Next.js won't have a handler for the OPTIONS method.
Proposed fix
export interface FrontendApiProxyHandlers {
GET: RouteHandler;
POST: RouteHandler;
PUT: RouteHandler;
DELETE: RouteHandler;
PATCH: RouteHandler;
+ OPTIONS: RouteHandler;
}And update createFrontendApiProxyHandlers:
return {
GET: handler,
POST: handler,
PUT: handler,
DELETE: handler,
PATCH: handler,
+ OPTIONS: handler,
};🤖 Prompt for AI Agents
In `@packages/nextjs/src/proxy.ts` around lines 66 - 72, The interface
FrontendApiProxyHandlers is missing an OPTIONS handler which will break CORS
preflight requests; add an OPTIONS: RouteHandler entry to the
FrontendApiProxyHandlers interface and update createFrontendApiProxyHandlers to
include and return an OPTIONS handler that forwards preflight requests (responds
appropriately or proxies the OPTIONS request to the upstream FAPI) so Next.js
can handle CORS preflights—modify both the FrontendApiProxyHandlers type and the
createFrontendApiProxyHandlers function to include the OPTIONS symbol
consistently.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
…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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] I think this might be duped
| * 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jacekradko required if frontendApiProxy is present right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
| '@clerk/backend': minor | ||
| '@clerk/nextjs': minor | ||
| '@clerk/express': minor | ||
| --- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| --- | |
| '@clerk/shared': minor | |
| --- |
jacekradko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just minor comments
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