Having trouble deleting cookies
Answered
North Pacific hake posted this in #help-forum
North Pacific hakeOP
Hi there, I am having trouble removing cookies with a server action.
I am calling the server action like so:
and the action is so:
The error is
Also seems like the cookies might be cached or something, even if I delete them they come back.
I am calling the server action like so:
import { logoutUser } from "@/app/actions/auth/logoutUser";
import { redirect } from "next/navigation";
const Logout = () => {
logoutUser();
redirect("/");
};
export default Logout;and the action is so:
"use server";
import constants from "@/app/lib/constants";
import { getPocketBase } from "@/app/lib/pb";
import { cookies } from "next/headers";
export const logoutUser = async () => {
const cookieStore = cookies();
const cookie = cookieStore.get(constants.AUTH_COOKIE_NAME);
const pb = getPocketBase(cookie?.value || "");
pb.authStore.clear();
cookieStore.delete(constants.AUTH_COOKIE_NAME);
};The error is
Cookies can only be modified in a Server Action or Route Handler. however, it is a server action or not?Also seems like the cookies might be cached or something, even if I delete them they come back.
Answered by Ray
const middleware = async (req) => {
const cookie = req.cookies.get(constants.AUTH_COOKIE_NAME)?.value;
const pb = getPocketBase(
req.cookies.get(constants.AUTH_COOKIE_NAME)?.value || ""
);
if (cookie) {
const res = NextResponse.next();
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});
try {
await pb.collection("users").authRefresh();
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.delete(constants.AUTH_COOKIE_NAME);
return res;
}
return res;
}
}57 Replies
you can't excute in the page directly
can you do this instead?
<button onClick={logoutUser}>logout</button>or with form in server component
<form action={logoutUser}>
<button>logout</button>
</form>@Ray tsx
<button onClick={logoutUser}>logout</button>
North Pacific hakeOP
this one does not seem to work
leads to this:
@North Pacific hake this one does not seem to work
need to be in client component
North Pacific hakeOP
ah sec let me try
@North Pacific hake ah sec let me try
<button onClick={() => logoutUser()}>logout</button>sorry, should be this
@Ray or with form in server component
ts
<form action={logoutUser}>
<button>logout</button>
</form>
use with form like this if you don't want to use client component
@Ray ts
<button onClick={() => logoutUser()}>logout</button>
sorry, should be this
North Pacific hakeOP
didn't cause error however the cookie is still there
@North Pacific hake didn't cause error however the cookie is still there
cookies().delete(constants.AUTH_COOKIE_NAME);@Ray ts
cookies().delete(constants.AUTH_COOKIE_NAME);
North Pacific hakeOP
its already as part of the function
this is how i am verifying the cookie
and it passes to the protected route
import { cookies } from "next/headers";
import constants from "../lib/constants";
import { getPocketBase } from "../lib/pb";
import { redirect } from "next/navigation";
const UserRouteProtection = () => {
const cookieStore = cookies();
const cookie = cookieStore.get(constants.AUTH_COOKIE_NAME);
const pb = getPocketBase(cookie?.value || "");
const isAuthenticated = pb.authStore.isValid;
if (!isAuthenticated) {
redirect("/login");
}
return;
};
export default UserRouteProtection;@North Pacific hake its already as part of the function
call the function like this
cookies().delete(constants.AUTH_COOKIE_NAME);North Pacific hakeOP
when i exit the db and i go to the protected route it redirects to /login and then deletes the cookie correctly
and when i start the db and i refresh the cookie remains gone
i think its cached or something
@Ray call the function like this
ts
cookies().delete(constants.AUTH_COOKIE_NAME);
North Pacific hakeOP
cookieStore.delete(constants.AUTH_COOKIE_NAME);
cookies().delete(constants.AUTH_COOKIE_NAME);
i have one right after the other still same thing sadly
cookies().delete(constants.AUTH_COOKIE_NAME);
i have one right after the other still same thing sadly
@North Pacific hake and when i start the db and i refresh the cookie remains gone
rename middleware.js to _middleware.js and try the whole process again
@Ray rename middleware.js to _middleware.js and try the whole process again
North Pacific hakeOP
that worked, howcome?
something wrong in your middleware
@Ray something wrong in your middleware
North Pacific hakeOP
import { NextResponse } from "next/server";
import constants from "./app/lib/constants";
import { getPocketBase } from "./app/lib/pb";
const middleware = async (req) => {
console.log(`[middleware] ${req.method} ${req.url}`);
const pb = getPocketBase(
req.cookies.get(constants.AUTH_COOKIE_NAME)?.value || ""
);
if (req.method === "GET" && pb.authStore.isValid) {
const res = NextResponse.next();
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});
try {
await pb.collection("users").authRefresh();
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.delete(constants.AUTH_COOKIE_NAME);
return res;
}
return res;
}
};
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};its based of what you helped me with the other day
i commented out
that fixed it
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});that fixed it
pb.authStore.isValid && (await pb.collection("users").authRefresh());
@Ray pb.authStore.isValid && (await pb.collection("users").authRefresh());
North Pacific hakeOP
no dice
change to this
try {
pb.authStore.isValid && (await pb.collection("users").authRefresh());
} catch (error) {
pb.authStore.clear();
}@Ray change to this
ts
try {
pb.authStore.isValid && (await pb.collection("users").authRefresh());
} catch (error) {
pb.authStore.clear();
}
North Pacific hakeOP
still same thing
@North Pacific hake i commented out
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});
that fixed it
North Pacific hakeOP
this is the culprit i believe
@North Pacific hake this is the culprit i believe
const middleware = async (req) => {
const cookie = req.cookies.get(constants.AUTH_COOKIE_NAME)?.value;
const pb = getPocketBase(
req.cookies.get(constants.AUTH_COOKIE_NAME)?.value || ""
);
if (cookie) {
const res = NextResponse.next();
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});
try {
await pb.collection("users").authRefresh();
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.delete(constants.AUTH_COOKIE_NAME);
return res;
}
return res;
}
}Answer
@Ray ts
const middleware = async (req) => {
const cookie = req.cookies.get(constants.AUTH_COOKIE_NAME)?.value;
const pb = getPocketBase(
req.cookies.get(constants.AUTH_COOKIE_NAME)?.value || ""
);
if (cookie) {
const res = NextResponse.next();
pb.authStore.onChange(() => {
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
});
try {
await pb.collection("users").authRefresh();
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.delete(constants.AUTH_COOKIE_NAME);
return res;
}
return res;
}
}
North Pacific hakeOP
i ended up rewriting the whole thing
if (pb.authStore.isValid) {
const res = NextResponse.next();
try {
await pb.collection("users").authRefresh();
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.clear(constants.AUTH_COOKIE_NAME);
return res;
}
} else {
return NextResponse.next();
}how come yours has syntax highliting?
const middleware = async (req) => {
console.log(`[middleware] ${req.method} ${req.url}`);
const pb = getPocketBase(
req.cookies.get(constants.AUTH_COOKIE_NAME)?.value || ""
);
if (pb.authStore.isValid) {
const res = NextResponse.next();
try {
await pb.collection("users").authRefresh();
res.headers.append(
"Set-Cookie",
`${constants.AUTH_COOKIE_NAME}=${pb.authStore.exportToCookie()}`
);
} catch (e) {
const res = NextResponse.redirect(new URL("/login", req.url));
pb.authStore.clear();
res.cookies.clear(constants.AUTH_COOKIE_NAME);
return res;
}
} else {
return NextResponse.next();
}
};North Pacific hakeOP
ooo
i think your solution is better overall thanks
@Ray no prob😀
North Pacific hakeOP
in theory this middleware should give you a unique cookie every time right?
@North Pacific hake in theory this middleware should give you a unique cookie every time right?
what do you mean unique cookie?
North Pacific hakeOP
authRefresh gives you a new auth token right?
yes
North Pacific hakeOP
i console logged it three times and every time it was the same value
check the cookie expire time
in the dev console
the token might not change but the expire time will update
North Pacific hakeOP
says "session"
i can't recall it, maybe you should check the doc on pocketbase
North Pacific hakeOP
alright thanks
closing browser cleared it looks like
see the expire day now?
@Ray see the expire day now?
North Pacific hakeOP
unfortunately no
@North Pacific hake unfortunately no
check the token option in settings page on pb admin