| name | authenticate-server-actions-like-api-routes |
| description | Authenticate server actions with the same rigor as API routes (session, token, CSRF). Use when implementing or securing Next.js server actions. |
Authenticate Server Actions Like API Routes
Impact: CRITICAL (prevents unauthorized access to server mutations)
Server Actions (functions with "use server") are exposed as public endpoints, just like API routes. Always verify authentication and authorization inside each Server Action—do not rely solely on middleware, layout guards, or page-level checks, as Server Actions can be invoked directly.
Next.js documentation explicitly states: "Treat Server Actions with the same security considerations as public-facing API endpoints, and verify if the user is allowed to perform a mutation."
Incorrect (no authentication check):
'use server';
export async function deleteUser(userId: string) {
await db.user.delete({ where: { id: userId } });
return { success: true };
}
Correct (authentication inside the action):
'use server';
import { verifySession } from '@/lib/auth';
import { unauthorized } from '@/lib/errors';
export async function deleteUser(userId: string) {
const session = await verifySession();
if (!session) {
throw unauthorized('Must be logged in');
}
if (session.user.role !== 'admin' && session.user.id !== userId) {
throw unauthorized('Cannot delete other users');
}
await db.user.delete({ where: { id: userId } });
return { success: true };
}
With input validation:
'use server';
import { verifySession } from '@/lib/auth';
import { z } from 'zod';
const updateProfileSchema = z.object({
userId: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
});
export async function updateProfile(data: unknown) {
const validated = updateProfileSchema.parse(data);
const session = await verifySession();
if (!session) {
throw new Error('Unauthorized');
}
if (session.user.id !== validated.userId) {
throw new Error('Can only update own profile');
}
await db.user.update({
where: { id: validated.userId },
data: {
name: validated.name,
email: validated.email,
},
});
return { success: true };
}
Reference: https://nextjs.org/docs/app/guides/authentication