Next.js Discord

Discord Forum

How to set cookies on a page?

Answered
Barbary Lion posted this in #help-forum
Open in Discord
Barbary LionOP
I want to have a page (/login) where a state cookie will be set and after that the user should be redirected but it doesn't work. This is my code:
import { redirect, RedirectType } from "next/navigation";
import { cookies } from "next/headers";

import { COOKIE_NAME_PREFIX } from "@/constants/guidelines";
import { encode } from "@/lib/utils";

const generateRandomState = (): string => {
    return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};

const generateAuthorizationURL = (state: string): string => {
    const data = {
        client_id: process.env.CLIENT_ID,
        redirect_uri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`,
        response_type: "code",
        scope: ["identify", "guilds", "email"].join(" "),
        state
    };

    return `https://discord.com/api/oauth2/authorize?${encode(data)}`;
};

export default function Page() {
    const state = generateRandomState();
    const authorizationURL = generateAuthorizationURL(state);

    cookies().set(COOKIE_NAME_PREFIX + "state", state, {
        secure: process.env.NODE_ENV === "production",
        httpOnly: true,
        sameSite: "lax",
        path: "/"
    });

    return redirect(authorizationURL, RedirectType.push);
}
Answered by joulev
You cannot set cookies in a server component. This is a fundamental limitation of the app router that you can’t work around.

In this case though sounds like it doesn’t have to be a page, since you are not rendering any react here. If you use a route handler instead it should still work. And you can set cookies in route handlers normally.
View full answer

4 Replies

@Barbary Lion I want to have a page (/login) where a state cookie will be set and after that the user should be redirected but it doesn't work. This is my code: tsx import { redirect, RedirectType } from "next/navigation"; import { cookies } from "next/headers"; import { COOKIE_NAME_PREFIX } from "@/constants/guidelines"; import { encode } from "@/lib/utils"; const generateRandomState = (): string => { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); }; const generateAuthorizationURL = (state: string): string => { const data = { client_id: process.env.CLIENT_ID, redirect_uri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`, response_type: "code", scope: ["identify", "guilds", "email"].join(" "), state }; return `https://discord.com/api/oauth2/authorize?${encode(data)}`; }; export default function Page() { const state = generateRandomState(); const authorizationURL = generateAuthorizationURL(state); cookies().set(COOKIE_NAME_PREFIX + "state", state, { secure: process.env.NODE_ENV === "production", httpOnly: true, sameSite: "lax", path: "/" }); return redirect(authorizationURL, RedirectType.push); }
You cannot set cookies in a server component. This is a fundamental limitation of the app router that you can’t work around.

In this case though sounds like it doesn’t have to be a page, since you are not rendering any react here. If you use a route handler instead it should still work. And you can set cookies in route handlers normally.
Answer
If he wanted to do it the way he typed out he would have to do really weird things with having a component that sets a cookie when it mounts then redirects, just a silly thing to try and do. What Joulev said is the way
just adding an interesting concoction into the mix: it's not possible because the next server already sent the headers and some HTML to the client right away before the RSC code is even executed, which makes it not possible to put set-cookie headers.
Barbary LionOP
Okay thanks guys. I’ll gonna do it with the route handler then 👍🏽