Next.js Discord

Discord Forum

Server action cookie mutation

Answered
Alex posted this in #help-forum
Open in Discord
Avatar
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.
View full answer

14 Replies

Avatar
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
Avatar
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
Avatar
server action need to work with form, event handler or useEffect
Avatar
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;
};
Avatar
yes you need server action to set the cookies
or set it in middleware
but I think you should set it in the LoginForm
Avatar
the code you have should move to middleware
Avatar
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.
Avatar
nm, I'm just moving the session create logic to middleware and keep the rest the way it is.
Answer