nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
22.87k stars 3.08k forks source link

Authjs v5 redirecting to the wrong URL #10928

Closed IncognitoTGT closed 1 day ago

IncognitoTGT commented 4 weeks ago

Environment

  System:
    OS: macOS 14.5
    CPU: (8) arm64 Apple M2
    Memory: 1019.91 MB / 24.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 21.6.2 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 10.2.4 - /opt/homebrew/bin/npm
    pnpm: 8.15.4 - /opt/homebrew/bin/pnpm
    bun: 1.0.26 - /usr/local/bin/bun
  Browsers:
    Chrome: 124.0.6367.203
    Chrome Canary: 126.0.6478.2
    Safari: 17.5
    Safari Technology Preview: 17.4
  npmPackages:
    next: 14.2.3 => 14.2.3 
    next-auth: 5.0.0-beta.18 => 5.0.0-beta.18 
    react: ^18.2.0 => 18.2.0 

Reproduction URL

https://github.com/spaceness/stardust/

Describe the issue

When I use Auth.js with an OAuth provider, like in my case Auth0, it redirects to localhost:3000 even if I'm logging in through a VSCode devtunnels or Tailscale funnel. In fact, this issue actually happens on every other URL.

There is an error with the server expecting the tunnel's URL but getting localhost.

How to reproduce

Setup the repository (only the nextauth and the DB stuff), and then try to login with a non localhost URL.

Expected behavior

It should redirect from the initial URL where the attempt was initiated from.

kevinmitch14 commented 4 weeks ago

I'm working with subdomains and it seems with v5 I am getting redirected to localhost:3000 for a lot of things as opposed to the subdomain I am initiating from. v4 is not doing this.

IncognitoTGT commented 4 weeks ago

For me I needed to set the HOST env variable but that'd just replace NEXTAUTH_URL in v4, which isn't really what I want since then it becomes a single domain application.

kevinmitch14 commented 4 weeks ago

Yeah, same here. It works but we are using multi tenant, so it makes no sense since we don't know the HOST at build time, only runtime. Been trying to hack something together now for a couple of days, would love to use v5 but the redirections are just a no-go right now.

Meierschlumpf commented 4 weeks ago

For me with docker it's redirecting to the internal docker url, for example: http://df3d663300c4:3000/

One idea I had on how to fix this is that when providing the full callback url (with base url), it should not use the request url and instead use the full callback url provided. In this way it would be possible to for example just run the following code:

await signIn(provider, {
        ...options,
        redirect: false,
        callbackUrl: new URL(callbackUrl, window.location.href).href,
})

Which would then be used to automatically get the correct callback url. In theory this can just be provided from the user and checked in the callback-url.ts file or it could even be run under the hood of signIn and construct the url from the window.location.href in there. I would be open to contribute one of both ways if one of the maintainers accepts this proposal.

sithembiso commented 4 weeks ago

I'm having a similar issue.

On mine, I have multiple subdomains with corresponding OAuth applications setup on both Google and Microsoft. The domains I'm using are localhost:3000 for dev, testing.example.com for qa, app.example.com for production. For some reason, localhost works correctly, but every time the user logs in on testing.example.com, it redirects to app.example.com every time. I have no idea where it's getting that domain from.

I believe it's taking the root domain example.com which we are redirecting to app.example.com on the DNS. However, I'm still not sure WHY its taking that in the first place.

I have added AUTH_URL and NEXTAUTH_URL setting it to testing.example.com, but it's not respecting that either.

StGeass commented 3 weeks ago

Similar problem with local development, I have two apps on local.mysite.com/app and local.mysite.com/crm, eventually if I don't set AUTH_URL it redirects to localhost:3000, but if I set it, the routing stops working correctly and I get UnknownAction: Cannot parse action error

ndom91 commented 3 weeks ago

Few things to mention here.

  1. Can you all include which version of next-auth@5.0.0-beta.* you're using? It should be the latest ideally.
  2. By default you'll be redirected back to your hostname/api/auth/callback/github (for exampe). For this to work, you'll need to do 2 thigns: 2.a. Ensure that URL is added in your OAuth provider's allowed callback URLs 2.b. Passed as the callbackUrl to the provider (done by default)
  3. If behind a reverse proxy, you'll also want to enable trustHost: true in your Auth.js config (or use the AUTH_TRUST_HOST=true env var) (docs)

Let me know if that helps any of you :pray: If not, like I said, please check yuo're on the latest version and provide some more details please

IncognitoTGT commented 3 weeks ago
  1. 5.0.0-beta.18
  2. Yes this is setup
  3. So is this
kevinmitch14 commented 3 weeks ago

@ndom91 I've provided a basic repro in https://github.com/nextauthjs/next-auth/issues/10915 without using any OAuth providers, I believe it could be a similar issue.

Meierschlumpf commented 3 weeks ago
  1. 5.0.0-beta.18
  2. Yes this is setup
  3. Not sure about this with docker, but trustHost is set any way.

I think the main issue here is that in

https://github.com/nextauthjs/next-auth/blob/1c17b78d54ec32e50f8c83a214ec2fc6df251368/packages/core/src/lib/utils/callback-url.ts#L21

It's using the url.origin which will not be the url of the users browser when behind a proxy or something

ndom91 commented 3 weeks ago

Thanks for the quick response all!

https://github.com/nextauthjs/next-auth/blob/1c17b78d54ec32e50f8c83a214ec2fc6df251368/packages/core/src/lib/utils/callback-url.ts#L21

It's using the url.origin which will not be the url of the users browser when behind a proxy or something

Hmm yeah that seems like it might be a bug, it should also take into account, for example, the x-forwarded-for header if the trustHost option is passed.

I'll take a look at the aforementioned repro above 🤔

IncognitoTGT commented 3 weeks ago

Yeah, for mine it seems to be checking req.url To reproduce my repo you really just need a postgres db (easy to spin up with docker) and the auth0 creds then auth should work

ndom91 commented 3 weeks ago

So I'm doing some digging through the code and I've found the following relevant parts:

Regarding the actionUrl, i.e. the base URL for all actions like session, callback, signIn, etc. (i.e. https://example.com/auth/session, http://localhost:3000/api/auth/signin):

  1. config.trustHost is auto-detected and set to true when any of the following env vars are set: AUTH_TRUST_HOST, CF_PAGES, VERCEL, AUTH_URL, NEXTAUTH_URL. But also when NODE_ENV !== 'production'.
  2. If !trustHost it'll error out early on when asserting config options
  3. If you set an AUTH_URL/NEXTAUTH_URL, it'll just use that when constructing the action URL, however if those aren't set, it'll generate the action URL like this:
// From packages/core/src/lib/utils/env.ts:71
// Pseudocode:

const detectedHost = headers.get("x-forwarded-host") ?? headers.get("host")
const detectedProtocol =
  headers.get("x-forwarded-proto") ?? protocol ?? "https"
const _protocol = detectedProtocol.endsWith(":")
  ? detectedProtocol
  : detectedProtocol + ":"

url = new URL(`${_protocol}//${detectedHost}`)

return new URL(`${url}/${action}`)

It doesn't look like trustHost/AUTH_TRUST_HOST is really used anywhere else, maybe its a legacy thing that's stuck around? It just checks that its set and errors out if it isn't, as far as I can tell :thinking:

Then, after that base action URL is generated, we get to the part where it appends the callbackUrl, for example, during the signIn action:

// From packages/next-auth/src/lib/actions.ts:25 
// Pseudocode:

const callbackUrl = redirectTo?.toString() ?? headers.get("Referer") ?? "/"
const signInURL = createActionURL(...)

signInURL.searchParams.append("callbackUrl", callbackUrl)
return signInURL.toString()

So long story short, without AUTH_URL, it looks like the callbackUrl is based off of the Referer header. Also you can override it with the redirectTo option. This wuold be passed in an object as the second argument to signIn() (for examlpe)

Regarding the callback-url cookie. It doesn't seem to be being used in this flow. I tried to reproduce what @kevinmitch14 mentioned in this issue, but I couldn't reproduce the cookie missing the subdomian. For example, when visiting my local dev server via http://db.app.lan:3000, the cookie was correctly set to http://db.app.lan:3000. Maybe that test.localhost issue is something particular in regard to localhost? :thinking:

kevinmitch14 commented 3 weeks ago

Hey @ndom91, attached a video just to make sure we are on the same page. No AUTH_URL. https://github.com/nextauthjs/next-auth/assets/55989505/48178483-dbfb-4a1e-a6fa-dcbfbbfe7fac

ndom91 commented 3 weeks ago

@kevinmitch14 thanks for the quick video! Can you share that repo? Looks like a nice minimal reproduction..

But yeah, so it looks like the callbackUrl that i mentioned in the second code snippet, that gets appended onto an action URL, like http://tenant1.localhost:3000/api/auth/signin?callbackUrl=.. did have the subdomain on it. But then it still sent the POST request to localhost:3000/api/auth/callback/credentials (w/o subdomain).

So it looks to me like the critical piece(s) of code are at packages/core/src/lib/utils/env.ts:50 (link), the createActionURL function.

This takes two different paths, dpending on whether AUTH_URL/NEXTAUTH_URL are set or not. Just like you demonstrated in your video.

Btw, sidenote, but since v5 only the AUTH_* environment variables are necessary / recommended. You can drop the NEXTAUTH_* ones.

kevinmitch14 commented 3 weeks ago

@ndom91 its the same one in the issue #10915. https://github.com/kevinmitch14/next-auth-subdomains

Btw, sidenote, but since v5 only the AUTH* environment variables are necessary / recommended. You can drop the NEXTAUTH* ones.

Thanks, I've been changing between v4/v5 so just have both. But in reality I don't have any set, because I don't know it at build time. It depends on the subdomain being used.

ndom91 commented 3 weeks ago

Basically, that createAcitonURL function is the one that generates the http://localhost:3000/api/auth/callback/credentials URL that eventually got POSTed to toward the beginning of your video, in the failure case.

We can see from the code that in the case of not having an AUTH_URL, it'll build this URL based off of first the x-forwarded-host and if that's not available, then headers.get('host').

Ex:

export function createActionURL(
  action: AuthAction,
  protocol: string,
  headers: Headers,
  envObject: any,
  basePath?: string
): URL {
  let envUrl = envObject.AUTH_URL ?? envObject.NEXTAUTH_URL

  let url: URL
  if (envUrl) {
    url = new URL(envUrl)
    if (basePath && basePath !== "/" && url.pathname !== "/") {
      logger.warn(
        url.pathname === basePath
          ? "env-url-basepath-redundant"
          : "env-url-basepath-mismatch"
      )
      url.pathname = "/"
    }
  } else {
    const detectedHost = headers.get("x-forwarded-host") ?? headers.get("host")
    const detectedProtocol =
      headers.get("x-forwarded-proto") ?? protocol ?? "https"
    const _protocol = detectedProtocol.endsWith(":")
      ? detectedProtocol
      : detectedProtocol + ":"

    url = new URL(`${_protocol}//${detectedHost}`)
  }
ndom91 commented 3 weeks ago

@kevinmitch14 so I cloned your repro and was abel to reproduce the same issue as you.

It seems that the issue comes from the <form action".." URL that is put into that default signIn page.

For the case of the Credentials provider, that comes from provider.callbackUrl. Doing some more digging to see where exactly that's set now..

kevinmitch14 commented 3 weeks ago

Interesting, I never noticed that. 🤔

For reference, the same flow works in v4 as normal. I think there's a v4 setup in my repo that is commented out. I do think I was having the similar issues when using the EmailProvider too, so I'm not sure if it's just related to CredentialsProvider

ndom91 commented 3 weeks ago

Are you using Next.js middleware in when using v4? Everythign else is the same?

It looks like the req.url is being reported as localhost:3000, no matter what host I'm actually visiting via.

For example, my random domain that /etc/host pointed at 127.0.0.1 is db.puff.lan. And visting http://db.puff.lan:3000/auth/signin results in the request that's being passed to the entrypoint of Auth.js being reported as http://localhost:3000/auth/signin?callbackUrl=http%3A%2F%2Fdb.puff.lan%3A3000%2F.

I also added some logging to the "root" http handler's that we export from NextAuth() in auth.ts. i.e. the function you expose in your ../[...nextauth]/route.ts and it alsoo reports it's request.url to be http://localhost:3000/auth/signin?callbackUrl=http%3A%2F%2Fdb.puff.lan%3A3000%2F when visiting http://db.puff.lan:3000/auth/signin?callbackUrl=http%3A%2F%2Fdb.puff.lan%3A3000%2F in the browser (i.e. clicking on "Sign In" and being redirected to default signin page).

image

I'm a bit at a loss for where to look next haha

kevinmitch14 commented 3 weeks ago

Yeah middleware is exact same, just changes in [...nextauth]/route.ts and app/[tenant]/page.tsx to revert back to v4.

Seeing the same as you: request.url is the base localhost URL, but host and x-forwarded-host has the subdomain attached to it.

Regardless, in v4, it does everything on the subdomain.

Screenshot 2024-05-19 at 14 53 24
IncognitoTGT commented 3 weeks ago

Yeah req.url can only be changed by setting the --host flag in next dev

Also for me, it actually redirects to https://localhost:3000 if I'm on a https secured domain, so there's likely something going on with the URL getting modifed.

IncognitoTGT commented 3 weeks ago

I forgot to add the original error, but this is the error logged to the console when this redirect happens:

error {
  error: 'unauthorized_client',
  error_description: 'The redirect URI is wrong. You sent https://localhost:3000, and we expected https://[redacted]'
}
[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error: TODO: Handle OIDC response body error
    at handleOAuth (webpack://stardust/node_modules/.pnpm/@auth+core@0.31.0/node_modules/@auth/core/lib/actions/callback/oauth/callback.js?c749:86:1)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at Module.callback (webpack://stardust/node_modules/.pnpm/@auth+core@0.31.0/node_modules/@auth/core/lib/actions/callback/index.js?aa74:22:1)
    at AuthInternal (webpack://stardust/node_modules/.pnpm/@auth+core@0.31.0/node_modules/@auth/core/lib/index.js?9b22:27:1)
    at Auth (webpack://stardust/node_modules/.pnpm/@auth+core@0.31.0/node_modules/@auth/core/index.js?4209:109:1)
    at <anonymous> (webpack://next/dist/esm/server/future/route-modules/app-route/module.js:207:37)
    at e_.execute (webpack://next/dist/esm/server/future/route-modules/app-route/module.js:122:26)
    at e_.handle (webpack://next/dist/esm/server/future/route-modules/app-route/module.js:269:30)
    at doRender (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:2273:30)
    at cacheEntry.responseCache.get.routeKind (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:2580:30)
    at DevServer.renderToResponseWithComponentsImpl (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:2454:24)
    at DevServer.renderPageComponent (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:3024:16)
    at DevServer.renderToResponseImpl (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:3086:24)
    at DevServer.pipeImpl (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:1544:21)
    at DevServer.NextNodeServer.handleCatchallRenderRequest (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/next-server.ts:1007:7)
    at DevServer.handleRequestImpl (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/base-server.ts:1325:9)
    at <anonymous> (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/dev/next-dev-server.ts:461:14)
    at Span.traceAsyncFn (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/trace/trace.ts:141:14)
    at DevServer.handleRequest (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/dev/next-dev-server.ts:459:20)
    at invokeRender (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/lib/router-server.ts:266:11)
    at handleRequest (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/lib/router-server.ts:512:16)
    at NextCustomServer.requestHandlerImpl (/Users/tgt/stardust/node_modules/.pnpm/next@14.2.3_react-dom@18.2.0_react@18.2.0/node_modules/next/src/server/lib/router-server.ts:558:7)
[auth][details]: {
  "provider": "auth0"
}

Setting hostname also then does not set the port to the correct one. Sorry for not including this detail eariler

ajin-iqness commented 3 weeks ago

I do face this weird issue. After being logged in, I could see the cookie authjs.callback-url is been set to http://localhost:3000 in my PROD for a second and then been corrected to my PROD url http://aaa.bbb.com. Due to this at times it's been redirected to http://localhost:3000 when session timeout. I have no traces of http://localhost:3000 anywhere in my code or environment variable. I haven't set AUTH_URL as it's not necessary for v5 and I faced some other issues while setting it.

I use "next": "14.1.4" "next-auth": "^5.0.0-beta.18",

PAHXO commented 3 weeks ago

I'm having the same issue. I have set to AUTH_TRUST_HOST=true. and I have checked that my reverse proxy(traefik) passes the x-forwarded-host header correctly. but I still get redirected back to "https://0.0.0.0:3000/api/auth/signin/auth0" when I click to login via auth0.

PAHXO commented 3 weeks ago

Fixed my issue by using those two environment variables.

  - AUTH_TRUST_HOST=false 
  - AUTH_URL=https://app.mydomain.com/api/auth 

This should work for now, until the issue is fixed.

ndom91 commented 3 weeks ago

Yeah a workaround for avoiding the auto-parsing of the origin, etc. is to set it manually with AUTH_URL, that should do the trick for anyone running into this atm who just wants to move on haha

IncognitoTGT commented 3 weeks ago

yeah lol but that means i can't use multiple domains haha there's a place in the repo where it uses req.url but i can't remember searching it at the moment try searchng in the repo

ndom91 commented 3 weeks ago

Yeah I know its not a fix, just wanted to confirm as a sort of work around.

Back on topic.. I'm honestly not sure what we can do if Next.js isn't reporting the right host. Someone mentioned that the x-forwarded-host header is correct though? Maybe we default to that instead?

Any other ideas?

kevinmitch14 commented 3 weeks ago

For some reason on v4, it redirects to the correct place so it seems like something in v5 is causing this?

For me atleast, I'm not sure about @IncognitoTGT's use-case as it could be a bit different.

IncognitoTGT commented 3 weeks ago

My use case is just multiple domains for a oauth provider that supports multple callbacks

benmarte commented 1 week ago

The same issue happens in Docker I made a repo so it's easier to reproduce if ya'll want to take a stab at debugging it in docker: https://github.com/nextauthjs/next-auth/discussions/8449#discussioncomment-9599951

Thanks.

Marv963 commented 1 week ago

I am experiencing the same issue with next-auth when using Next.js (version 14.2.3) and next-auth (^5.0.0-beta.18). My setup involves running Next.js inside a Docker container, behind Traefik as a reverse proxy. Traefik is configured to forward the X-Forwarded-Host header, which is successfully being sent.

Problem Details:

1. Default Callback URL:

When I do not set the AUTH_URL, next-auth sets the authjs.callback_url cookie to localhost:3000. As a result, when attempting to sign in with a provider, next-auth uses localhost:3000 for the redirect_uri. This leads to a redirect_uri_mismatch error from the provider.

2. Callback URL Override:

Passing a callbackUrl or redirectTo to the signIn method does not override the localhost:3000 value for redirect_uri.

3. Setting the AUTH_URL results in an SSL SELF_SIGNED_CERT_IN_CHAIN error.

Weirdly, it works when I start Next.js in development mode and subsequently set the AUTH_URL via the .env.local file. However, this does not help me since I need it to work in the production environment.

Expected Behavior: The authjs.callback_url should reflect the forwarded host from the X-Forwarded-Host header.

toshgoodson commented 1 week ago

I've found a workaround that works well for me.

My setup

My environment variables:

AUTH_TRUST_HOST=true
AUTH_REDIRECT_PROXY_URL=https://stable.dev.domain.com/api/auth
AUTH_SECRET=mysecret

The workaround code:

// In src/app/api/[...nextauth]/route.ts
import { handlers } from "@/auth"
import { NextRequest } from "next/server"

const reqWithTrustedOrigin = (req: NextRequest): NextRequest => {
    if (process.env.AUTH_TRUST_HOST !== 'true') return req
    const proto = req.headers.get('x-forwarded-proto')
    const host = req.headers.get('x-forwarded-host')
    if (!proto || !host) {
        console.warn("Missing x-forwarded-proto or x-forwarded-host headers.")
        return req
    }
    const envOrigin = `${proto}://${host}`
    const { href, origin } = req.nextUrl
    return new NextRequest(href.replace(origin, envOrigin), req)
}

export const GET = (req: NextRequest) => {
    return handlers.GET(reqWithTrustedOrigin(req))
}

export const POST = (req: NextRequest) => {
    return handlers.POST(reqWithTrustedOrigin(req))
}

This is based on https://github.com/nextauthjs/next-auth/blob/next-auth%405.0.0-beta.19/packages/next-auth/src/lib/env.ts#L6 where AUTH_URL is used to set the request origin. You would think setting AUTH_TRUST_HOST would do this automatically, but I guess it doesn't?

tunchunairarko commented 1 day ago
import { handlers } from "@/auth"
import { NextRequest } from "next/server"

const reqWithTrustedOrigin = (req: NextRequest): NextRequest => {
  if (process.env.AUTH_TRUST_HOST !== 'true') return req
  const proto = req.headers.get('x-forwarded-proto')
  const host = req.headers.get('x-forwarded-host')
  if (!proto || !host) {
      console.warn("Missing x-forwarded-proto or x-forwarded-host headers.")
      return req
  }
  const envOrigin = `${proto}://${host}`
  const { href, origin } = req.nextUrl
  return new NextRequest(href.replace(origin, envOrigin), req)
}

export const GET = (req: NextRequest) => {
  return handlers.GET(reqWithTrustedOrigin(req))
}

export const POST = (req: NextRequest) => {
  return handlers.POST(reqWithTrustedOrigin(req))
}

This works for me! Finally, I was about to give up.

IncognitoTGT commented 1 day ago

I've found a workaround that works well for me.

My setup

My environment variables:

AUTH_TRUST_HOST=true
AUTH_REDIRECT_PROXY_URL=https://stable.dev.domain.com/api/auth
AUTH_SECRET=mysecret

The workaround code:

// In src/app/api/[...nextauth]/route.ts
import { handlers } from "@/auth"
import { NextRequest } from "next/server"

const reqWithTrustedOrigin = (req: NextRequest): NextRequest => {
  if (process.env.AUTH_TRUST_HOST !== 'true') return req
  const proto = req.headers.get('x-forwarded-proto')
  const host = req.headers.get('x-forwarded-host')
  if (!proto || !host) {
      console.warn("Missing x-forwarded-proto or x-forwarded-host headers.")
      return req
  }
  const envOrigin = `${proto}://${host}`
  const { href, origin } = req.nextUrl
  return new NextRequest(href.replace(origin, envOrigin), req)
}

export const GET = (req: NextRequest) => {
  return handlers.GET(reqWithTrustedOrigin(req))
}

export const POST = (req: NextRequest) => {
  return handlers.POST(reqWithTrustedOrigin(req))
}

This is based on https://github.com/nextauthjs/next-auth/blob/next-auth%405.0.0-beta.19/packages/next-auth/src/lib/env.ts#L6 where AUTH_URL is used to set the request origin. You would think setting AUTH_TRUST_HOST would do this automatically, but I guess it doesn't?

Thank you for this. This works perfectly for me :)