Build invite redirects from the public origin
request.url carries the app's internal bind address (0.0.0.0:3000) because it runs behind a reverse proxy, so every invite link - valid or not - redirected to an unreachable https://0.0.0.0:3000/join. Uses NEXTAUTH_URL, which is the configured public origin and cannot be influenced by a request header, falling back to forwarded headers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,12 +13,26 @@ import { INVITE_COOKIE, INVITE_COOKIE_MAX_AGE, inspectInvite } from "@/lib/invit
|
||||
*/
|
||||
export const dynamic = "force-dynamic"
|
||||
|
||||
/**
|
||||
* The app binds 0.0.0.0:3000 behind a reverse proxy, so `request.url` carries the
|
||||
* internal address and redirects built from it are unreachable. NEXTAUTH_URL is the
|
||||
* configured public origin and cannot be influenced by a request header.
|
||||
*/
|
||||
function publicOrigin(request: Request): string {
|
||||
const configured = process.env.NEXTAUTH_URL
|
||||
if (configured) return configured.replace(/\/$/, "")
|
||||
|
||||
const host = request.headers.get("x-forwarded-host") ?? request.headers.get("host")
|
||||
const proto = request.headers.get("x-forwarded-proto") ?? "https"
|
||||
return host ? `${proto}://${host}` : new URL(request.url).origin
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: { token: string } }
|
||||
) {
|
||||
const { state } = await inspectInvite(params.token)
|
||||
const origin = new URL(request.url).origin
|
||||
const origin = publicOrigin(request)
|
||||
|
||||
if (state !== "valid") {
|
||||
return NextResponse.redirect(new URL(`/join?error=${state}`, origin))
|
||||
|
||||
Reference in New Issue
Block a user