Server Action Security
Answered
Carolina Dog posted this in #help-forum
Carolina DogOP
I'm still confused about the security of server actions.
For example. let's say i have a form where the user must be authenticated to submit the form. When using REST API and making an API Endpoint, we should first validate if the request has the session or not (authenticated or not). Then we should validate the body data type maybe using zod or somethinge. This is because anyone can access the API Endpoint if they know the endpoint link just by sending a request through Postman, or any other app (Doesnt have to go through our website).
How about when using server actions? Is it accessible outside of our website? Or is it must be triggered using our website? Do i need to validate the user's session and request body? Even if there's already a client side validation in the form?
Thank you.
For example. let's say i have a form where the user must be authenticated to submit the form. When using REST API and making an API Endpoint, we should first validate if the request has the session or not (authenticated or not). Then we should validate the body data type maybe using zod or somethinge. This is because anyone can access the API Endpoint if they know the endpoint link just by sending a request through Postman, or any other app (Doesnt have to go through our website).
How about when using server actions? Is it accessible outside of our website? Or is it must be triggered using our website? Do i need to validate the user's session and request body? Even if there's already a client side validation in the form?
Thank you.
Answered by B33fb0n3
hey, server actions might be confusing. To answer your question (the post title), yes they are secure, but you should still check the user input. If you trust the user you can execute code without additional check, but normally you won't. So check the user input and continue executing. Server actions can only be triggert inside your app. To do auth stuff there are many things you CAN do. So without knowing the whole project, I can't give you a clean recommendation 🙂 @Carolina Dog
11 Replies
hey, server actions might be confusing. To answer your question (the post title), yes they are secure, but you should still check the user input. If you trust the user you can execute code without additional check, but normally you won't. So check the user input and continue executing. Server actions can only be triggert inside your app. To do auth stuff there are many things you CAN do. So without knowing the whole project, I can't give you a clean recommendation 🙂 @Carolina Dog
Answer
@B33fb0n3 hey, server actions might be confusing. To answer your question (the post title), yes they are secure, but you should still check the user input. If you trust the user you can execute code without additional check, but normally you won't. So check the user input and continue executing. Server actions can only be triggert inside your app. To do auth stuff there are many things you CAN do. So without knowing the whole project, I can't give you a clean recommendation 🙂 <@348294011368374285>
Carolina DogOP
Let's say that for that form page, I've validated the user session trhough middleware. So that means i don't have to validate the user's session again in the server actions right? because It can only be triggered inside my app
Yea, that’s my point of view ðŸ‘
Carolina DogOP
But let's say I'm validating using zod + react hook form, is it still possible if the user bypass the rhf + zod validation? So I still need to validate the data in the action?
The client can bypass everything that works on the clientside. If you check the data only on serverside, the client can’t bypass it. So you valide the data only once and it’s secure, because the validation is serverside
@B33fb0n3 The client can bypass everything that works on the clientside. If you check the data only on serverside, the client can’t bypass it. So you valide the data only once and it’s secure, because the validation is serverside
Carolina DogOP
Ah I see.
Thank you so much for your response!
Have a great day!
Thank you so much for your response!
Have a great day!
Harlequin Duck
From this doc: https://nextjs.org/blog/security-nextjs-server-components-actions#write it says:
It gives an example where within the server action, we verifies that the user is allowed to trigger the action.
Is there a better pattern to implement this? Writing canUserDoActionX for each server action feels cumbsersome?
The "use server" annotation exposes an end point that makes all exported functions invokable by the client. The identifiers is currently a hash of the source code location. As long as a user gets the handle to the id of an action, it can invoke it with any arguments.
As a result, those functions should always start by validating that the current user is allowed to invoke this action. Functions should also validate the integrity of each argument. This can be done manually or with a tool like zod.It gives an example where within the server action, we verifies that the user is allowed to trigger the action.
Is there a better pattern to implement this? Writing canUserDoActionX for each server action feels cumbsersome?
@Harlequin Duck From this doc: https://nextjs.org/blog/security-nextjs-server-components-actions#write it says:` The "use server" annotation exposes an end point that makes all exported functions invokable by the client. The identifiers is currently a hash of the source code location. As long as a user gets the handle to the id of an action, it can invoke it with any arguments.
As a result, those functions should always start by validating that the current user is allowed to invoke this action. Functions should also validate the integrity of each argument. This can be done manually or with a tool like zod.`
It gives an example where within the server action, we verifies that the user is allowed to trigger the action.
Is there a better pattern to implement this? Writing canUserDoActionX for each server action feels cumbsersome?
You can use a higher order function. I use the pattern quite a lot. Just change the withAuth logic to whatever you need
export function withAuth<T, P extends unknown[] = []>(
callback: (session: Session, ...data: P) => T | Promise<T>,
): (...data: P) => Promise<T> {
return async (...data: P) => {
const session = await auth();
if (!session) redirect("/login");
const result = await callback(session, ...data);
return result;
};
}"use server";
export const updateName = withAuth(async (session, name: string) => {
// do stuff
});@Harlequin Duck From this doc: https://nextjs.org/blog/security-nextjs-server-components-actions#write it says:` The "use server" annotation exposes an end point that makes all exported functions invokable by the client. The identifiers is currently a hash of the source code location. As long as a user gets the handle to the id of an action, it can invoke it with any arguments.
As a result, those functions should always start by validating that the current user is allowed to invoke this action. Functions should also validate the integrity of each argument. This can be done manually or with a tool like zod.`
It gives an example where within the server action, we verifies that the user is allowed to trigger the action.
Is there a better pattern to implement this? Writing canUserDoActionX for each server action feels cumbsersome?
Carolina DogOP
Wait but can I trigger server actions through Postman tho? If so how can I do it?