vercel / next.js

The React Framework
https://nextjs.org
MIT License
123.52k stars 26.35k forks source link

Cannot run Server Actions in GitHub Codespaces or VSCode Tunnel #58019

Open waki285 opened 8 months ago

waki285 commented 8 months ago

Link to the code that reproduces this issue

https://github.com/waki285/Server-Actions-Bug

To Reproduce

  1. Clone the repository in GitHub Codespaces or VSCode Tunnel.
  2. Start the server with next dev.
  3. Codespaces (or VSCode Tunnel) will automatically perform port forwarding and you can access the launched website through it.
  4. Click the "Execute Server Actions" button.
  5. An error will occur.

Current vs. Expected behavior

Expected: Server Actions are executed successfully and no errors occur.

Current: The following error occurs

`false` header with value `********-3000.***.devtunnels.ms` does not match `origin` header with value `localhost:3000` from a forwarded Server Actions request. Aborting the action.
 ⨯ Error: Invalid Server Actions request.
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at AsyncLocalStorage.run (node:async_hooks:346:14)

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022
Binaries:
  Node: 20.9.0
  npm: 10.2.2
  Yarn: N/A
  pnpm: 8.10.2
Relevant Packages:
  next: 14.0.2-canary.11
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router

Additional context

No response

Georgerowberry commented 8 months ago

Having the same issue here, middleware CORS not helping either

danieltott commented 8 months ago

I'm having this issue with a host that is being served behind an apache ProxyPass/ProxyPassReverse

lucienbl commented 8 months ago

Hello,

I had the same issue after upgrading from NextJS 13 to NextJS 14, my server is running behind an NGINX reverse proxy. Adding the following to the reverse proxy configuration resolved the issue :

proxy_set_header   Host               $host;
proxy_set_header   X-Real-IP          $remote_addr;
proxy_set_header   X-Forwarded-Proto  $scheme;
proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;

I hope this can help you resolve the issue on your end by adapting this solution to Apache etc...

Best regards.

danieltott commented 8 months ago

So Next 14 added some more protection against CSRF attacks. However it caused this problem we're all running in to. https://github.com/vercel/next.js/pull/57529 allows us to specify a list of allowed forwarded hosts, and it was released in v14.0.2-canary.4

I was able to fix this without messing with the proxy settings (which are configured automatically (and correctly) by apache) by doing the following:

experimental: {
  serverActions: {
    // edit: updated to new key. Was previously `allowedForwardedHosts`
    allowedOrigins: ['my-forwarded-host.com'],
  },
},
njfdev commented 8 months ago

I also had this issue and have confirmed that this works with GitHub Codespaces.

So Next 14 added some more protection against CSRF attacks. However it caused this problem we're all running in to. #57529 allows us to specify a list of allowed forwarded hosts, and it was released in v14.0.2-canary.4

I was able to fix this without messing with the proxy settings (which are configured automatically (and correctly) by apache) by doing the following:

  • Upgrade next to 14.0.2-canary.4
  • Add this to next.config:
experimental: {
  serverActions: {
    allowedForwardedHosts: ['my-forwarded-host.com'],
  },
},
waki285 commented 8 months ago

do i need to include subdomains?

So Next 14 added some more protection against CSRF attacks. However it caused this problem we're all running in to. #57529 allows us to specify a list of allowed forwarded hosts, and it was released in v14.0.2-canary.4

I was able to fix this without messing with the proxy settings (which are configured automatically (and correctly) by apache) by doing the following:

  • Upgrade next to 14.0.2-canary.4
  • Add this to next.config:
experimental: {
  serverActions: {
    allowedForwardedHosts: ['my-forwarded-host.com'],
  },
},
SAMXPS commented 8 months ago

Hello, I am having the same issue here with Nginx proxy. Tried to Upgrade next to 14.0.2-canary.4 and add allowedForwardedHosts but it is not working. Any documentation on how to set up allowedForwardedHosts correctly ?

njfdev commented 8 months ago

Hello, I am having the same issue here with Nginx proxy. Tried to Upgrade next to 14.0.2-canary.4 and add allowedForwardedHosts but it is not working. Any documentation on how to set up allowedForwardedHosts correctly ?

Not sure if there is any documentation, especially because it is not a full release yet. But you should be able to add this to your next.config.js and replace my-forwarded-host.com with the full domain (including subdomains) of your website being ran through the proxy:

experimental: {
  serverActions: {
    allowedForwardedHosts: ['my-forwarded-host.com'],
  },
},
corywatsonhcl commented 8 months ago

After upgrading to 14 I'm running into the same issue with a Next app being deployed via Docker. If I statically set a hostname using docker run or docker compose locally I can map it using allowedForwardedHosts and it works. However, when deploying to a cloud provider I don't have any control over the hostname. I do have the hostname available via an env variable, but as far as I can tell I can't use an env var in next.config.js. Any ideas on how to handle that situation?

danieltott commented 8 months ago

After upgrading to 14 I'm running into the same issue with a Next app being deployed via Docker. If I statically set a hostname using docker run or docker compose locally I can map it using allowedForwardedHosts and it works. However, when deploying to a cloud provider I don't have any control over the hostname. I do have the hostname available via an env variable, but as far as I can tell I can't use an env var in next.config.js. Any ideas on how to handle that situation?

If you manually install dotenv you can use env variables here! As long as they're the same at build time as run time that should work just fine 👍

corywatsonhcl commented 8 months ago

After upgrading to 14 I'm running into the same issue with a Next app being deployed via Docker. If I statically set a hostname using docker run or docker compose locally I can map it using allowedForwardedHosts and it works. However, when deploying to a cloud provider I don't have any control over the hostname. I do have the hostname available via an env variable, but as far as I can tell I can't use an env var in next.config.js. Any ideas on how to handle that situation?

If you manually install dotenv you can use env variables here! As long as they're the same at build time as run time that should work just fine 👍

@danieltott the issue is that with a cloud platform, I won't know the container host name until the container is run, which will be after the build was run to create the Docker image. It seems therefore that this approach is incompatible with output: standalone and that I'll need to use npm start to be able to use the env vars. That's unfortunate.

timneutkens commented 8 months ago

We've added an option experimental.serverActions.allowedOrigins in #58023 that allows you to add a list of allowed hosts. The reason it throws by default is that this is a layer of cross site request forgery protection.

Shu is currently out of office till next week but we'll add support for wildcard patterns once he's back.

djpiper28 commented 8 months ago

Hello, I am having the same issue here with Nginx proxy. Tried to Upgrade next to 14.0.2-canary.4 and add allowedForwardedHosts but it is not working. Any documentation on how to set up allowedForwardedHosts correctly ?

I set my allowed host for the hostname of the gateway of my the k8 cluster. I'm assuming with an nginx you can try localhost, 127.0.0.1 or 0.0.0.0 probably

yasz commented 8 months ago

when added prompt x-forwarded-host and host headers do not match origin header from a forwarded Server Actions request. ..

waki285 commented 8 months ago

not work in VSCode Tunnel. I tried both:

experimental: {
    serverActions: {
      allowedForwardedHosts: ["localhost", "xxxxxxxx-3000.xxx.devtunnels.ms"],
      allowedOrigins: ["xxxxxxxx-3000.xxx.devtunnels.ms", "localhost:3000"]
    }
  }
  experimental: {
    serverActions: {
      allowedForwardedHosts: ["localhost", "xxxxxxxx-3000.xxx.devtunnels.ms"],
      allowedOrigins: ["https://xxxxxxxx-3000.xxx.devtunnels.ms", "localhost:3000"]
    }
  }

error:

`x-forwarded-host` header with value `xxxxxxxx-3000.xxx.devtunnels.ms` does not match `origin` header with value `localhost:3000` from a forwarded Server Actions request. Aborting the action.
 ⨯ Error: Invalid Server Actions request.
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
waki285 commented 8 months ago

Sorry, I copied and pasted the Origin in Request Headers directly into allowedOrigins and it worked!

devraj commented 8 months ago

Sorry, I copied and pasted the Origin in Request Headers directly into allowedOrigins and it worked!

Could you please share an example of the version of the configuration that worked for you?

ideactionagency commented 8 months ago

Sorry, I copied and pasted the Origin in Request Headers directly into allowedOrigins and it worked!

Could you please share an example of the version of the configuration that worked for you?

/** @type {import("next").NextConfig} */
module.exports = {
    experimental: {
        serverActions: {
            allowedOrigins: ["demo.example.com:3000"],
        },
    },
}

this worked for me

devraj commented 8 months ago

Sorry, I copied and pasted the Origin in Request Headers directly into allowedOrigins and it worked!

Could you please share an example of the version of the configuration that worked for you?

/** @type {import("next").NextConfig} */
module.exports = {
    experimental: {
        serverActions: {
            allowedOrigins: ["demo.example.com:3000"],
        },
    },
}

this worked for me

Following on from this comment using 14.0.3-canary.5 and allowedOrigins works, note that you are not to include http or https protocols, but just have the domain name.

Hopefully there's some official docs that come with the future releases.

jide commented 8 months ago

I have the same issue, and allowedOrigins fixes it for fixed subdomains. But I use wildcards subdomains and rewrite them to an app route.

In this case, how can I allow subdomains ?

devraj commented 8 months ago

I have the same issue, and allowedOrigins fixes it for fixed subdomains. But I use wildcards subdomains and rewrite them to an app route.

In this case, how can I allow subdomains ?

@jide have a look at this comment higher up in the thread by @timneutkens looks like wildcard support is around the corner.

jide commented 8 months ago

@devraj thanks, but to me the PR seems to only cover a fixed list of origins. See this part of the code :

if (serverActions?.allowedOrigins?.includes(originDomain)) {

And I did not see any mention of wildcard support. Did I miss something ?

jide commented 8 months ago

BTW, this issue will make the vercel platforms example not work https://demo.vercel.pub/platforms-starter-kit

meleyal commented 8 months ago

Shu is currently out of office till next week but we'll add support for wildcard patterns once he's back.

@timneutkens any update on wildcard support?

Wei102193 commented 8 months ago

upgraded to 14.0.2 and added

module.exports = {
    experimental: {
        serverActions: {
            allowedOrigins: ["localhost:3000", "demo.your-actual-domain.com],
        },
    },
}

solved my problem

rshaul commented 8 months ago

This is affecting me and I'm not even using server actions just route handlers & middleware. Multi tenant saas app. When I dump out the request object headers nextjs seems to be modifying the x-forwarded-host header value and lieing about what it was actually sent as? And this was shipped in a 0.0.1 update? Uhhh...

Reverting to 14.0.1 fixes issue.

waki285 commented 8 months ago
experimental: {
    serverActions: {
      allowedOrigins: ["xxxxxxxx-3000.xxx.devtunnels.ms" /* or Codespace port forward url, no including scheme */, "localhost:3000"]
    }
  }

I have been able to confirm that this solves the problem.

jide commented 8 months ago

@waki285 Sorry but this is not completed: We still cant use wildacrds in allowOrigins.

@timneutkens @meleyal

brayden-wong commented 8 months ago

I also need this to be a wildcard origin, as I will be working with multiple different origins.

QuyetTV1991 commented 7 months ago

This configure is worked for me when I'm working in Codespaces /* @type {import('next').NextConfig} / const nextConfig = { experimental: { serverActions: { allowedOrigins: [ "https://musical-rotary-phone-xp9q5r4wjqx2wvv-3000.app.github.dev/", "localhost:3000", ], }, mdxRs: true, serverComponentsExternalPackages: ["mongoose"], }, };

module.exports = nextConfig;

jide commented 7 months ago

This commit adds wildcard support : https://github.com/vercel/next.js/commit/6fbff29a2e312eee0c129184aee4105b6a186771

Available in canary for now.

waki285 commented 7 months ago

Is this a way to set this options in .env? I don't want to commit next.config.js with my personal codespace domain.

gtjamesa commented 7 months ago

Is this a way to set this options in .env? I don't want to commit next.config.js with my personal codespace domain.

You can use process.env.MY_VAR in your next config

amaksimovich2 commented 7 months ago

But as I know process.env.MY_VAR value should be set up while build time. And it will not work with docker solution and different env variables while running time. Correct me, if I'm mistaken

arman-bolatuly commented 7 months ago

hi team. i used all of examples. but, they r not working? how can i resolve it? thanks!

ghost commented 6 months ago

None of these options work for me, Next.js seems to ignore the allowOrigins property. Is there any other workaround, or even a way to just disable this security feature?

matthewca commented 6 months ago

This is working for me in Codespaces with Next.js 14.1.0:

if (process.env.NODE_ENV == 'development') {
    module.exports = {
        experimental: {
            serverActions: {
                allowedOrigins: ['localhost:3000'],
            },
        },
    }
}
stefanosandes commented 5 months ago

We've added an option experimental.serverActions.allowedOrigins in #58023 that allows you to add a list of allowed hosts. The reason it throws by default is that this is a layer of cross site request forgery protection.

Shu is currently out of office till next week but we'll add support for wildcard patterns once he's back.

Okay, this solves the problem for a limited number of domains. But what can I do if my SaaS works with many custom domains, one custom domain per customer?

My specific case is described here: https://github.com/vercel/next.js/discussions/62050

jide commented 5 months ago

@stefanosandes You can now use wildcards, like this :

allowedOrigins: ["*.mydomain.com"]

But you need to use canary version.

See https://github.com/vercel/next.js/issues/58019#issuecomment-1858651491

step2341 commented 1 month ago

Im having this issue also in 14.2.4 when we attempt to deploy to test. Looks like issue 58295 was maybe closed prematurely? On some endpoints it seems to work, but on others particularly those involving dynamic nested routes, it fails.

within my nextjs config i have this:

experimental: { serverActions: { bodySizeLimit: '2mb', allowedOrigins: ['xxx.com', 'localhost:3000'], allowedForwardedHosts: ['xxx.com', 'localhost:3000'] } }, where xxx is our domain but it doesnt seem to make any difference.

x-forwarded-host header with value localhost:3000 does not match origin header with value 'xxx.com` from a forwarded Server Actions request. Aborting the action.

any help would be appreciated.

mokshsinghji commented 2 weeks ago

Im having this issue also in 14.2.4 when we attempt to deploy to test. Looks like issue 58295 was maybe closed prematurely? On some endpoints it seems to work, but on others particularly those involving dynamic nested routes, it fails.

within my nextjs config i have this:

experimental: { serverActions: { bodySizeLimit: '2mb', allowedOrigins: ['xxx.com', 'localhost:3000'], allowedForwardedHosts: ['xxx.com', 'localhost:3000'] } }, where xxx is our domain but it doesnt seem to make any difference.

x-forwarded-host header with value localhost:3000 does not match origin header with value 'xxx.com` from a forwarded Server Actions request. Aborting the action.

any help would be appreciated.

I found that using nginx as a reverse proxy for my application was setting the x-forwarded-host to localhost:3000, so i added this line onto my config. If you are using a reverse proxy, it might help:

server {
    server_name  <DOMAIN_HERE>;
    location / {
        proxy_set_header x-forwarded-host <DOMAIN_HERE>;
        proxy_pass http://localhost:<PORT_HOSTED_AT>;
    }
}
raphaeltm commented 1 week ago

@stefanosandes You can now use wildcards, like this :

allowedOrigins: ["*.mydomain.com"]

But you need to use canary version.

See #58019 (comment)

I cannot seem to make this work. I'm on 14.3.0-canary.65. Though I do not know how Next.js canary releases work/are structured, so I'm not sure which canary release includes the wildcards. To be fair, I've tried with and without wildcards, and nothing works. I'm trying to make this play nice with GitHub Codespaces so that I can easily share config and tooling with students.

My config looks like this:

const nextConfig = {
  experimental: {
    serverActions: {
      allowedOrigins: [
        "*.app.github.dev",
      ],
    }
  },
};

I've also use the domain directly:

const nextConfig = {
  experimental: {
    serverActions: {
      allowedOrigins: [
        "fluffy-train-7vvwjrgxgr2w59v-3000.app.github.dev",
      ],
    }
  },
};

I still keep getting:

`x-forwarded-host` header with value `fluffy-train-7vvwjrgxgr2w59v-3000.app.github.dev` does not match `origin` header with value `localhost:3000` from a forwarded Server Actions request. Aborting the action.