-
Notifications
You must be signed in to change notification settings - Fork 4k
fix: support X-Forwarded-* headers in proxy environments (#10928) #13323
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
|
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. |
☕️ Reasoning
This PR restores X-Forwarded-Host and X-Forwarded-Proto header handling that was present in [email protected] 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
[email protected], 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
[email protected]: /packages/next-auth/src/utils/detect-origin.tsand/packages/next-auth/src/core/index.ts🧢 Checklist
🎫 Affected issues
Fixes: #10928
📌 Resources