# Securing Server Actions — Next.js

Source: https://www.skillbyai.com/en/nextjs/m-secure

> Every action is a public endpoint.

## Authenticate, authorise, validate

A Server Action can be called with any arguments by anyone who can reach your site, just like an API endpoint. Inside every action: **authenticate** the user (read the session), **authorise** the specific operation (may this user edit this record?), and **validate** all input with a schema (for example Zod) rather than trusting form fields. Return safe error messages, avoid leaking internal details, and rate-limit sensitive actions.

## A guarded action (sketch)

Pattern for real actions; getSession and db are your own modules. Not run here.

```tsx
"use server";
import { z } from "zod";
import { getSession } from "@/lib/auth";

const Input = z.object({ id: z.string().uuid(), price: z.number().positive().max(1_000_000) });

export async function setPrice(raw: unknown) {
  const session = await getSession();
  if (!session) return { error: "Please sign in" };                 // authenticate
  const input = Input.safeParse(raw);
  if (!input.success) return { error: "Invalid input" };           // validate
  const product = await db.product.find(input.data.id);
  if (product.ownerId !== session.userId) return { error: "Not allowed" };   // authorise
  await db.product.update(input.data.id, { price: input.data.price });
  return { ok: true };
}
```

## Never trust hidden fields

Users can change any value sent from the browser, including hidden inputs and ids; check permissions on the server.

**Quiz:** Why must Server Actions check authorisation?

- [x] They can be called directly with any arguments, like public endpoints
- [ ] React checks permissions automatically
- [ ] They only run in development
- [ ] Forms cannot be submitted by attackers

*Answer:* They can be called directly with any arguments, like public endpoints. Treat actions as public APIs.
