- Next.js
- Security & Authentication Architecture
- Server Action Security: CSRF, Authorization & Validation
Server Action Security: CSRF, Authorization & Validation
Server Actions are publicly accessible HTTP POST endpoints and must be secured with the same defense-in-depth posture as public REST APIs. Next.js enforces built-in CSRF protection by validating the Origin and Host headers. However, developers must explicitly enforce user authentication, role-based authorization, and schema validation (e.g. Zod) inside every Server Action.
Learning Objectives
Understand how Next.js compares Origin and Host headers to mitigate CSRF attacks.
Enforce server-side authentication and role-based access control inside Server Actions.
Validate untrusted input data using schemas (Zod/Valibot) before business logic execution.
Prevent IDOR (Insecure Direct Object Reference) vulnerabilities.
Prerequisites & Background Knowledge
Why Interviewers Care
Top priority for senior and staff frontend engineering interviews. Security vulnerabilities in Server Actions are a common blindspot.
The Challenge
Why must Server Actions be treated as public HTTP endpoints? Implement a secure Server Action with authentication verification, role-based authorization, Zod schema validation, and IDOR protection.
Code Architecture & Implementation
1// app/actions/projects.ts2'use server';34import { z } from 'zod';5import { getAuthenticatedSession } from '@/lib/auth';6import { db } from '@/lib/db';7import { projects } from '@/lib/schema';8import { eq, and } from 'drizzle-orm';910const DeleteProjectSchema = z.object({11 projectId: z.string().uuid('Invalid project identifier'),12});1314export async function deleteProjectAction(formData: FormData) {15 // 1. AUTHENTICATION CHECK: Never trust client parameters for identity16 const session = await getAuthenticatedSession();17 if (!session || !session.userId) {18 throw new Error('Authentication required');19 }2021 // 2. INPUT VALIDATION: Ensure strict types and formats22 const parsed = DeleteProjectSchema.safeParse({23 projectId: formData.get('projectId'),24 });25 if (!parsed.success) {26 return { error: 'Invalid input payload' };27 }2829 const { projectId } = parsed.data;3031 // 3. AUTHORIZATION & IDOR PREVENTION:32 // Ensure the user actually OWNS the project or has admin privileges!33 const deleted = await db34 .delete(projects)35 .where(36 and(37 eq(projects.id, projectId),38 eq(projects.ownerId, session.userId) // Prevents deleting other users' projects!39 )40 )41 .returning();4243 if (deleted.length === 0) {44 return { error: 'Project not found or unauthorized' };45 }4647 return { success: true };48}
Architectural Explanation
Because Server Actions look like regular TypeScript functions, developers often assume they are private. In reality, Next.js exposes them as HTTP endpoints. Next.js provides built-in CSRF mitigation: it verifies that the Origin header matches the Host header. However, CSRF protection does NOT authenticate the user. Developers must: 1) Verify the user session from cookies, 2) Validate inputs with Zod, 3) Verify authorization (RBAC), and 4) Ensure the user has permission to mutate that specific entity (preventing IDOR).
Common Mistakes & Anti-Patterns
Passing the user ID from the client: `action(userId, data)`, allowing attackers to pass another user's ID.
Relying solely on UI checks (e.g. hiding the delete button) without verifying permissions on the server.
Catching auth errors and returning generic 200 OK without preventing unauthorized writes.
Interview Follow-Up Traps
The interviewer asks: "Do I need CSRF tokens for Server Actions?" Explain that Next.js uses Origin and Host header verification (SameSite cookie policy + Origin comparison), eliminating the need for manual CSRF tokens for modern browsers, though allowedOrigins must be configured for complex reverse proxies.
Frequently Asked Questions
How do you structure reusable authorization middleware for Server Actions?
Use action wrapper utilities (e.g. `createSafeActionClient` from next-safe-action) to enforce auth and validation pipelines.
What happens if allowedOrigins is misconfigured behind a reverse proxy?
Next.js will reject valid form submissions with a 403 Forbidden or "Invalid origin" error.
