Next.js Discord

Discord Forum

Session & Cookies

Answered
Turkish Angora posted this in #help-forum
Open in Discord
Turkish AngoraOP
I'm using next 14 with app router , have a backend api with auth/login endpoint , I'm also using zod and react-hook-form ,
I want to use cookies to keep the token of the user , I'm getting an error that I can't set cookies in client compoent
Answered by Ray
cookies() need to be use in server action/ route handler. create a server action like this and import it to the client
// actions.ts

'use server'

import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export async function signin() {
  try {
    const response = await fetch("http://127.0.0.1:8000/auth/login/", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    const domain = new URL(response.url).host
    const user = await response.json();
    const { token } = user;
    cookies().set({
      name: 'token',
      value: token,
      domain,
      httponly:true
    })
    redirect("/home");
  } catch (error) {
    console.error("Sign-in error:", error);
    return { error }
  }
}
View full answer

9 Replies

Turkish AngoraOP
const onSubmit: SubmitHandler<InputsType> = async (data) => {
    try {
      const response = await fetch("http://127.0.0.1:8000/auth/login/", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });
      const user = await response.json();
      const { token } = user;
      sessionStorage.setItem("token", token);
      router.push("/home");
    } catch (error) {
      console.error("Sign-in error:", error);
    }
  };


I have this in my page.tsx "use client"
@Turkish Angora javascript const onSubmit: SubmitHandler<InputsType> = async (data) => { try { const response = await fetch("http://127.0.0.1:8000/auth/login/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }); const user = await response.json(); const { token } = user; sessionStorage.setItem("token", token); router.push("/home"); } catch (error) { console.error("Sign-in error:", error); } }; I have this in my page.tsx "use client"
cookies() need to be use in server action/ route handler. create a server action like this and import it to the client
// actions.ts

'use server'

import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export async function signin() {
  try {
    const response = await fetch("http://127.0.0.1:8000/auth/login/", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    const domain = new URL(response.url).host
    const user = await response.json();
    const { token } = user;
    cookies().set({
      name: 'token',
      value: token,
      domain,
      httponly:true
    })
    redirect("/home");
  } catch (error) {
    console.error("Sign-in error:", error);
    return { error }
  }
}
Answer
Giant Angora
You can also simply append cookie values in the client (browser) with:
const key = 'my-app-token';
const value = 'some-token';

document.cookie = `${key}=${value}; `; 

this would be a session cookie, if you want a persisting one you need to set a max age (seconds) or expires:
// 1 hour
document.cookie = `${key}=${value}; max-age: 3600; `;

// exact time
const time = new Date();
document.cookie = `${key}=${value}; expires=${time.toUTCString()}; `;
Giant Angora
note that these examples will only allow the cookie to be seen from the path(+subpaths) it is created in, so adding cookie from mysite.com/user/login will not work in mysite.com/shop .

if you want site wide cookie you need to explicitly define the root path into the cookie string document.cookie = "token=sometoken; path=/; " (or any other common path that is enough)
Turkish AngoraOP
If I want to logout I need to remove the cookie , I found that I need to use : https://github.com/andreizanik/cookies-next
is ther a better solution
@Turkish Angora If I want to logout I need to remove the cookie , I found that I need to use : https://github.com/andreizanik/cookies-next is ther a better solution
this would work if the cookie is not httponly
if you are using httponly, create another server action for signout
'use server'

export async function signout() {
  cookies().delete("token")
  redirect("/")
}
@Turkish Angora If I want to logout I need to remove the cookie , I found that I need to use : https://github.com/andreizanik/cookies-next is ther a better solution
Giant Angora
You can also just delete a cookie in the client with eg.

const del = (key: string, path = '/') => {
  document.cookie = `${key}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}; domain=${window.location.hostname};`
}