Move CSRF handling into security middleware#47
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR moves CSRF enforcement into framework middleware, adds cookie-based client config and a csrf.input() helper, removes ChangesCSRF Middleware Redesign
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/security/src/next/server.ts`:
- Around line 51-73: The code currently always sets the CSRF and client-config
cookies for every safe request in issueCsrfCookie; change it to short-circuit
and only set cookies when needed by reading existing cookies from the incoming
request (use request.cookies.get(config.csrf.cookie) and
request.cookies.get(SECURITY_CLIENT_CONFIG_COOKIE)), then: 1) for the CSRF
cookie, only set it when the cookie is missing or invalid — verify the existing
value using the csrf verification API you have (e.g., csrf.verify or equivalent)
instead of regenerating unconditionally; 2) for the client config cookie,
compute the new value with
serializeSecurityClientConfig(createSecurityClientConfig(config)) and only call
response.cookies.set for SECURITY_CLIENT_CONFIG_COOKIE when the serialized value
differs from the existing cookie value; keep using isSecureRequest(request) and
the same cookie options when setting. Ensure the rest of the flow (importing
NextResponse, returning undefined for non-safe or disabled CSRF) remains
unchanged.
In `@packages/security/src/nuxt/server.ts`:
- Around line 45-64: The issue: issueCsrfCookie currently resets both cookies on
every safe request causing unnecessary Set-Cookie headers; fix by checking
existing cookie values and only calling setCookie when absent, invalid, or
stale. In issueCsrfCookie use the incoming Request/H3Event to read current
cookies (check config.csrf.cookie and SECURITY_CLIENT_CONFIG_COOKIE), validate
the existing CSRF token (e.g., compare/verify with csrf.token or csrf.verify
equivalent) and compare serialized createSecurityClientConfig(config) to the
existing client-config cookie (or add a version/timestamp check), and only call
setCookie(...) for the specific cookie(s) that need updating rather than
unconditionally setting both.
- Around line 35-42: createRequest currently rebuilds a Nuxt Request without the
incoming body, breaking protect() -> readFormToken() paths; fix by reading the
event body and passing it into the new Request: in createRequest (and any helper
it calls) read the raw request body (e.g. await readBody(event) or await
getRawBody(event.node.req) as appropriate), preserve Content-Type and other
relevant headers, and include the body in the Request constructor options so
readFormToken() can access form data; ensure the body read is awaited before
constructing the Request to avoid consuming the stream twice and keep
createRequest async.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f0a543c3-5500-4dc9-8479-638ad087625f
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (65)
apps/blog-next/app/api/login/route.tsapps/blog-next/app/api/register/route.tsapps/blog-next/app/login/actions.tsapps/blog-next/app/login/page.tsxapps/blog-next/app/register/actions.tsapps/blog-next/app/register/page.tsxapps/blog-next/config/security.tsapps/blog-next/proxy.tsapps/blog-next/tests/login-page.test.mjsapps/blog-next/tests/register-page.test.mjsapps/blog-nuxt/app/pages/login/index.vueapps/blog-nuxt/app/pages/register/index.vueapps/blog-nuxt/config/security.tsapps/blog-nuxt/server/api/login.post.tsapps/blog-nuxt/server/api/register.post.tsapps/blog-nuxt/server/middleware/csrf.tsapps/blog-sveltekit/config/security.tsapps/blog-sveltekit/src/hooks.server.tsapps/blog-sveltekit/src/routes/+layout.server.tsapps/blog-sveltekit/src/routes/login/+page.server.tsapps/blog-sveltekit/src/routes/login/+page.svelteapps/blog-sveltekit/src/routes/register/+page.server.tsapps/blog-sveltekit/src/routes/register/+page.svelteapps/blog-sveltekit/src/routes/super-admin/login/+page.server.tsapps/blog-sveltekit/src/routes/super-admin/login/+page.svelteapps/blog-sveltekit/tests/auth-page-actions.test.mjsapps/docs/docs/auth/current-auth-client.mdapps/docs/docs/forms/client-usage.mdapps/docs/docs/forms/framework-integration.mdapps/docs/docs/forms/server-validation.mdapps/docs/docs/security.mdpackages/adapter-next/src/client.tspackages/adapter-sveltekit/tests/runtime.test.tspackages/auth/src/next/server.tspackages/auth/src/nuxt-shim.d.tspackages/auth/src/nuxt/server.tspackages/auth/src/runtime/csrfCookie.tspackages/auth/src/sveltekit/server.tspackages/auth/tests/framework.test.tspackages/forms/src/client-security.tspackages/forms/src/contracts.tspackages/forms/src/internal/client.tspackages/forms/src/security.tspackages/forms/tests/client.test.tspackages/forms/tests/client.type.test.tspackages/forms/tests/contracts.test.tspackages/forms/tests/contracts.type.test.tspackages/forms/tests/security.test.tspackages/security/package.jsonpackages/security/src/client-config.tspackages/security/src/client.tspackages/security/src/contracts.tspackages/security/src/csrf.tspackages/security/src/framework-shim.d.tspackages/security/src/index.tspackages/security/src/next/server.tspackages/security/src/nuxt/server.tspackages/security/src/sveltekit/server.tspackages/security/tests/client.test.tspackages/security/tests/client.type.test.tspackages/security/tests/docs-smoke.test.tspackages/security/tests/framework-middleware.test.tspackages/security/tests/package.test.tspackages/security/tests/sveltekit.test.tspackages/security/tsup.config.ts
💤 Files with no reviewable changes (21)
- apps/blog-nuxt/server/api/register.post.ts
- apps/blog-next/app/api/register/route.ts
- apps/blog-nuxt/server/api/login.post.ts
- apps/blog-next/app/login/actions.ts
- packages/adapter-next/src/client.ts
- packages/forms/tests/client.type.test.ts
- apps/blog-next/app/login/page.tsx
- apps/blog-next/tests/login-page.test.mjs
- packages/auth/src/runtime/csrfCookie.ts
- apps/blog-next/app/api/login/route.ts
- apps/blog-next/app/register/page.tsx
- packages/security/tests/client.type.test.ts
- packages/auth/src/nuxt-shim.d.ts
- apps/blog-nuxt/app/pages/login/index.vue
- packages/auth/src/sveltekit/server.ts
- apps/blog-next/app/register/actions.ts
- apps/blog-sveltekit/tests/auth-page-actions.test.mjs
- apps/blog-next/tests/register-page.test.mjs
- packages/forms/src/security.ts
- apps/docs/docs/auth/current-auth-client.md
- apps/blog-nuxt/app/pages/register/index.vue
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/security/tests/framework-middleware.test.ts`:
- Around line 112-113: The test currently asserts the previous token value isn't
present by checking staleConfigResponse?.headers.get('set-cookie') doesn't
contain `XSRF-TOKEN=${encodeURIComponent(token)`, which can false-negative if a
new token with a different value is issued; instead assert that no CSRF cookie
is reissued by checking the cookie name prefix is absent (e.g. ensure the
'set-cookie' header does not contain the `XSRF-TOKEN=` name) while still
ensuring the configuration cookie exists via `SECURITY_CLIENT_CONFIG_COOKIE=`;
update the two expectations that reference
staleConfigResponse?.headers.get('set-cookie') accordingly so the first checks
for the cookie name absence and the second still checks for
`${SECURITY_CLIENT_CONFIG_COOKIE}=`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 325f535b-9d5c-49a2-9f82-6bf72559ec15
📒 Files selected for processing (3)
packages/security/src/next/server.tspackages/security/src/nuxt/server.tspackages/security/tests/framework-middleware.test.ts
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Documentation