Server action cookie mutation
Answered
Alex posted this in #help-forum
AlexOP
I am trying to create a session cookie for my auth system if there isn't one already. a have a ts file containing a function that does exactly that. I marked the file and the function as server action. now I am calling this function from a server component. all parents are server components. But still I am getting
Cookies can only be modified in a Server Action or Route Handler.
Any ideas?Answered by Alex
nm, I'm just moving the session create logic to middleware and keep the rest the way it is.
14 Replies
It is because server action is a function invoke on client side which make a POST request to the route
when you call it in server component, it is just a normal server side function
AlexOP
yes, well, that's what I thought. At first, I didn't have the "use server" marks, and it was just a normal function but still I got the error
server action need to work with form, event handler or useEffect
AlexOP
Yes i know, but apparently I don't even need a server action
I have this file, it's a wrapper for the login form:
import { checkPrivaleges } from "@/auth/privaleges";
...
export default async function Login() {
await checkPrivaleges(AllowedPrivaleges.GUEST);
return (
<UserPageTile title="Log in" description="Login to access the Admin Dashboard where you can manage your events" className="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5 col-xxl-4">
<LoginForm />
</UserPageTile>
);
}
it calls this function:
export const checkPrivaleges = async (allowed: AllowedPrivaleges, checkEmailVerified: boolean = true): Promise<UserWithSession> => {
const { user, session } = await validateRequest();
...
};
which calls this function:
export const validateRequest = async (): Promise<UserWithSession> => {
const sessionId = cookies().get(lucia.sessionCookieName)?.value ?? null;
if (!sessionId) {
return {
user: null,
session: null,
};
}
const result = await lucia.validateSession(sessionId);
// next.js throws when you attempt to set cookie when rendering page
try {
if (result.session && result.session.fresh) {
const sessionCookie = lucia.createSessionCookie(result.session.id);
cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
}
if (!result.session) {
const sessionCookie = lucia.createBlankSessionCookie();
cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
}
} catch (e) {
console.error(e);
}
return result;
};
yes you need server action to set the cookies
or set it in middleware
but I think you should set it in the LoginForm
the code you have should move to middleware
AlexOP
Well, currently when using
checkPrivaleges(AllowedPrivaleges.GUEST);
I can pass an option for setting which users are allowed on the page. with middleware that would not be that easy.AlexOP
nm, I'm just moving the session create logic to middleware and keep the rest the way it is.
Answer