fix: support X-Forwarded-* headers in proxy environments (#10928)#13323
fix: support X-Forwarded-* headers in proxy environments (#10928)#13323UNILORN wants to merge 1 commit intonextauthjs:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
@UNILORN is attempting to deploy a commit to the authjs Team on Vercel. A member of the Team first needs to authorize it. |
Broken Link Checker
1) /getting-started/migrate-to-better-auth
|
|
I have identified a workaround on the application side. Given this, the changes in this PR may not be required, so I am marking it as a draft for the time being. |
Can you explain the workaround? Meanwhile, I've applied your patch and managed to make the redirect work. |
|
While testing on the application side, we observed the following behavior: req.headers.get("x-forwarded-host") // 'example.com'
req.headers.get("x-forwarded-proto") // 'https'
req.headers.get("host") // 'example.com'
req.url // 'https://my-app-pod-1234:3000/api/auth/...'After implementing a wrapper for the request in function wrapWithForwardedHost(req: NextRequest): NextRequest {
const headersList = headers();
const forwardedHost = headersList.get('x-forwarded-host');
const forwardedProto = headersList.get('x-forwarded-proto');
if (!forwardedHost || !forwardedProto) {
return req;
}
const newHeaders = new Headers(req.headers);
newHeaders.set('x-forwarded-host', forwardedHost);
newHeaders.set('x-forwarded-proto', forwardedProto);
const originalUrl = new URL(req.url);
const protocol = forwardedProto.endsWith(':') ? forwardedProto : `${forwardedProto}:`;
const correctedUrl = `${protocol}//${forwardedHost}${originalUrl.pathname}${originalUrl.search}`;
return new Request(correctedUrl, {
method: req.method,
headers: newHeaders,
body: req.body,
// @ts-expect-error duplex is required for streaming request bodies
duplex: 'half',
}) as unknown as NextRequest;
}
export function GET(req: NextRequest) {
return handlers.GET(wrapWithForwardedHost(req));
}
export function POST(req: NextRequest) {
return handlers.POST(wrapWithForwardedHost(req));
}The changes I pushed earlier include this logic implemented on the Auth.js side. Could you please review this update and let me know if there are any issues? I apologize for putting the PR back into draft status after you had already reviewed it, but I would appreciate it if you could review it once again. |
Hi, I applied your code to |
|
@kirinse |
|
Any Updates regarding fixing this issue? I'm also facing same issue |
|
What is the status of the review for this PR?
I verified that the fix works by testing both main and fix/10928 branches separately. |
☕️ Reasoning
This PR restores X-Forwarded-Host and X-Forwarded-Proto header handling that was present in next-auth@4.24.13 but was lost during the migration to the current main branch architecture.
Problem
When running behind reverse proxies or load balancers (e.g., nginx, Vercel, Cloudflare), OAuth provider callback URLs are generated with internal hostnames instead of the public domain. This causes OAuth authentication to fail with "redirect_uri mismatch" errors.
In
next-auth@4.24.13, thetoInternalRequest()function useddetectOrigin()to extract the origin fromX-Forwarded-*headers. This logic was removed in the refactoring to the current architecture, where toInternalRequest() directly uses new URL(req.url) without considering proxy headers.Behavior
The fix only activates when one of the following conditions is met
References
next-auth@4.24.13: /packages/next-auth/src/utils/detect-origin.tsand/packages/next-auth/src/core/index.ts🧢 Checklist
🎫 Affected issues
Fixes: #10928
📌 Resources