Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions docs/content/docs/1.guides/2.first-party.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**
Expand All @@ -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

Expand Down
38 changes: 17 additions & 21 deletions packages/script/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -1040,7 +1033,14 @@ export default defineNuxtModule<ModuleOptions>({
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'
Expand Down Expand Up @@ -1069,14 +1069,10 @@ export default defineNuxtModule<ModuleOptions>({
// 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(
Expand Down
Loading