diff --git a/docs/content/docs/1.guides/2.first-party.md b/docs/content/docs/1.guides/2.first-party.md index 7071d3e86..b97969f42 100644 --- a/docs/content/docs/1.guides/2.first-party.md +++ b/docs/content/docs/1.guides/2.first-party.md @@ -280,16 +280,25 @@ export default defineNuxtConfig({ // Auto-generate and persist a secret to .env in dev mode. // Set to false to disable. autoGenerateSecret: true, - // Emit a per-request proxy page token into the SSR payload so - // client-driven proxy calls authenticate without pre-signed URLs. - // Set to false to keep the token out of the payload (e.g. for a - // stable response etag); client-side calls then need signed URLs. - pageToken: true, } } }) ``` +To disable proxy security entirely, set `security` to `false`: + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + scripts: { + // No secret is resolved or auto-generated, no page token is added to the + // SSR payload, and proxy endpoints pass requests through unverified. + security: false, + } +}) +``` + +This is useful when you need a deterministic SSR payload (e.g. to compute a stable response `etag`), since the per-request page token otherwise changes the payload on every request. Proxy endpoints stay functional but unprotected against quota abuse. + #### Troubleshooting **Signed URLs return 403 after deploy** @@ -310,7 +319,7 @@ Page tokens are valid for 1 hour. If a user leaves a tab open longer than that, **Proxy token changes the response payload on every request** -The module injects a per-request page token into the SSR payload, so the response hash differs each request. If you compute a stable `etag`, set `security.pageToken: false` to keep the token out of the payload. Client-side proxy calls will then need explicitly signed URLs. +The module injects a per-request page token into the SSR payload, so the response hash differs each request. If you compute a stable `etag`, set `security: false` to disable proxy security entirely. Proxy endpoints then pass requests through without signature verification, so only do this if quota abuse on those endpoints is not a concern. #### Static Generation and SPA Mode diff --git a/packages/script/src/module.ts b/packages/script/src/module.ts index a71cc940a..e3ae9fd18 100644 --- a/packages/script/src/module.ts +++ b/packages/script/src/module.ts @@ -373,8 +373,12 @@ export interface ModuleOptions { * * The secret must be deterministic across deployments so that prerendered URLs * remain valid. Set it via `NUXT_SCRIPTS_PROXY_SECRET` or `security.secret`. + * + * Set to `false` to disable proxy security entirely: no secret is resolved or + * auto-generated, no page token is injected into the SSR payload, and proxy + * endpoints pass requests through without signature verification. */ - security?: { + security?: false | { /** * HMAC secret used to sign proxy URLs. * @@ -408,17 +412,6 @@ export interface ModuleOptions { * @default 3600 */ pageTokenMaxAge?: number - /** - * Emit a per-request proxy page token into the SSR payload so client-driven - * proxy calls authenticate without each URL being HMAC-signed up front. - * - * Set to `false` to keep the token out of the payload (e.g. when computing a - * stable response `etag`). Client-side proxy requests that rely on the token - * will then need explicitly signed URLs. - * - * @default true - */ - pageToken?: boolean } /** * Google Static Maps proxy configuration. @@ -1040,7 +1033,14 @@ export default defineNuxtModule({ const isStaticTarget = staticPresets.includes(nitroPreset) const isSpa = nuxt.options.ssr === false - if (anyHandlerRequiresSigning && (isSpa || isStaticTarget)) { + // Proxy security explicitly disabled: skip secret resolution and the page + // token plugin. `withSigning` passes requests through unverified. + if (config.security === false) { + if (anyHandlerRequiresSigning && !nuxt.options.dev) { + logger.info('[security] Proxy security disabled via `security: false`. Proxy endpoints will pass requests through without signature verification.') + } + } + else if (anyHandlerRequiresSigning && (isSpa || isStaticTarget)) { logger.warn( `[security] URL signing requires a server runtime${isStaticTarget ? ` (detected preset: ${nitroPreset})` : ' (ssr: false)'}.\n` + ' Proxy endpoints will work without signature verification.\n' @@ -1069,14 +1069,10 @@ export default defineNuxtModule({ // Emit a per-request page token during SSR so client-driven proxy // calls (reactive fetches, dynamic image helpers) authenticate via // `_pt` + `_ts` without needing each URL to be HMAC-signed up front. - // Opt out via `security.pageToken: false` to keep the token out of the - // SSR payload (e.g. for a stable response etag). - if (config.security?.pageToken !== false) { - addPlugin({ - src: await resolvePath('./runtime/plugins/proxy-token.server'), - mode: 'server', - }) - } + addPlugin({ + src: await resolvePath('./runtime/plugins/proxy-token.server'), + mode: 'server', + }) } else if (!nuxt.options.dev) { logger.warn(