Skip to content

Commit 0a7a524

Browse files
committed
fix: support X-Forwarded-* headers in proxy environments (#10928)
1 parent b4ef14a commit 0a7a524

File tree

1 file changed

+35
-2
lines changed
  • packages/core/src/lib/utils

1 file changed

+35
-2
lines changed

packages/core/src/lib/utils/web.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,40 @@ export async function toInternalRequest(
3535
// Defaults are usually set in the `init` function, but this is needed below
3636
config.basePath ??= "/auth"
3737

38-
const url = new URL(req.url)
38+
const headers = Object.fromEntries(req.headers)
39+
const forwardedHost = headers["x-forwarded-host"]
40+
const forwardedProto = headers["x-forwarded-proto"]
41+
42+
// Determine if we should trust forwarded headers
43+
// This mirrors the logic in setEnvDefaults but works before config is fully initialized
44+
const envObject =
45+
typeof process !== "undefined" && process.env ? process.env : {}
46+
const trustHost =
47+
config.trustHost ??
48+
!!(
49+
envObject.AUTH_URL ??
50+
envObject.AUTH_TRUST_HOST ??
51+
envObject.VERCEL ??
52+
envObject.CF_PAGES ??
53+
envObject.NODE_ENV !== "production"
54+
)
55+
56+
// Construct URL from forwarded headers if in trusted environment
57+
// This is necessary because req.url may contain internal pod/service names in proxied environments
58+
let url: URL
59+
if (trustHost && forwardedHost && forwardedProto) {
60+
const originalUrl = new URL(req.url)
61+
const protocol = forwardedProto.endsWith(":")
62+
? forwardedProto
63+
: `${forwardedProto}:`
64+
// Construct a completely new URL using the forwarded host/proto
65+
// This avoids issues where req.url contains internal kubernetes service names
66+
url = new URL(
67+
`${protocol}//${forwardedHost}${originalUrl.pathname}${originalUrl.search}`
68+
)
69+
} else {
70+
url = new URL(req.url)
71+
}
3972

4073
const { action, providerId } = parseActionAndProviderId(
4174
url.pathname,
@@ -47,7 +80,7 @@ export async function toInternalRequest(
4780
action,
4881
providerId,
4982
method: req.method,
50-
headers: Object.fromEntries(req.headers),
83+
headers,
5184
body: req.body ? await getBody(req) : undefined,
5285
cookies: parseCookie(req.headers.get("cookie") ?? "") ?? {},
5386
error: url.searchParams.get("error") ?? undefined,

0 commit comments

Comments
 (0)