"Cookies can only be modified in a Server Action or Route Handler" error
Unanswered
Dutch posted this in #help-forum
DutchOP
Hi guys . I'm new in nextjs and i created a rootlayout like below
verify.ts
it gives error on catch block "cookieManager.delete('token');"
what is the problem ?
export default async function RootLayout({ children }: Props) {
const locale = await getLocale();
const messages = await getMessages();
const user = await verify();
return (
<html className="h-full overflow-hidden" lang={locale}>
<body className="h-full overflow-hidden">
<AppRouterCacheProvider>
<NextIntlClientProvider messages={messages}>
<StoreProvider initialUser={user}>
<ToastProvider>{children}</ToastProvider>
</StoreProvider>
</NextIntlClientProvider>
</AppRouterCacheProvider>
</body>
</html>
);
}verify.ts
'use server';
import { getMe } from '@/lib/services/auth.service';
import { cookies } from 'next/headers';
export async function verify() {
let user: User | undefined;
const cookieManager = await cookies();
try {
const token = cookieManager.get('token');
if (token) {
user = await getMe();
if (!user) {
cookieManager.delete('token');
}
}
} catch {
cookieManager.delete('token');
}
return user;
}it gives error on catch block "cookieManager.delete('token');"
what is the problem ?
10 Replies
@Dutch Hi guys . I'm new in nextjs and i created a rootlayout like below
ts
export default async function RootLayout({ children }: Props) {
const locale = await getLocale();
const messages = await getMessages();
const user = await verify();
return (
<html className="h-full overflow-hidden" lang={locale}>
<body className="h-full overflow-hidden">
<AppRouterCacheProvider>
<NextIntlClientProvider messages={messages}>
<StoreProvider initialUser={user}>
<ToastProvider>{children}</ToastProvider>
</StoreProvider>
</NextIntlClientProvider>
</AppRouterCacheProvider>
</body>
</html>
);
}
verify.ts
ts
'use server';
import { getMe } from '@/lib/services/auth.service';
import { cookies } from 'next/headers';
export async function verify() {
let user: User | undefined;
const cookieManager = await cookies();
try {
const token = cookieManager.get('token');
if (token) {
user = await getMe();
if (!user) {
cookieManager.delete('token');
}
}
} catch {
cookieManager.delete('token');
}
return user;
}
it gives error on catch block "cookieManager.delete('token');"
what is the problem ?
When using a server action onthe server (like you doing here), it will be automatically translated to a normal function to avoid performance issues.
And that means, that you call for example
Iirc you can check auth in middleware and correctly remove/set cookies. Never check auth only inside your layout. Your page details may leak
And that means, that you call for example
cookieManager.delete('token'); inside your server side page. And that is not allowed. It's only allowed inside a server action or route handler.Iirc you can check auth in middleware and correctly remove/set cookies. Never check auth only inside your layout. Your page details may leak
DutchOP
i understand you but is it a good way to check auth in the middleware on every request ? i just store a token to cookie . i if client refresh the page, i get the cookie and check with it user has exists or not . we need a checking in middleware just do that ?
@Dutch i understand you but is it a good way to check auth in the middleware on every request ? i just store a token to cookie . i if client refresh the page, i get the cookie and check with it user has exists or not . we need a checking in middleware just do that ?
i understand you but is it a good way to check auth in the middleware on every request ?
its fine as long as you dont do fetching in middleware.ts/proxy.ts.
some people use middleware.ts/proxy.ts as "front-line" defense auth guard.
usually i just ignore the cookie if its invalid and return null and avoid using middleware.ts/proxy.ts at all.
extra: you dont need to worry about wasting resource of
getMe() or doing unecessary fetch of getMe() since you can just data-cache the data and it will be instantly returned@Dutch i understand you but is it a good way to check auth in the middleware on every request ? i just store a token to cookie . i if client refresh the page, i get the cookie and check with it user has exists or not . we need a checking in middleware just do that ?
What alfon says and: use middleware as long as there are no fetches. So just checking if the cookie valid by checking its JWT is completely fine. Like that you can redirect instantly to „/auth“ page if the user is not authenticated
I normally check the auth in the middleware (to route correctly), check on the page as well (to get user data) and if there are any route handlers/server actions, that the client can use, I check inside them too. To secure your app, you might want to do the same
I normally check the auth in the middleware (to route correctly), check on the page as well (to get user data) and if there are any route handlers/server actions, that the client can use, I check inside them too. To secure your app, you might want to do the same
Pacific sand lance
the issue is that you can't modify headers/cookies/anything related to request/response in RSCs
even if you call server action from RSC it's still called from within RSC
@B33fb0n3 When using a server action *on*the server (like you doing here), it will be automatically translated to a normal function to avoid performance issues.
And that means, that you call for example `cookieManager.delete('token');` inside your server side page. And that is not allowed. It's only allowed inside a server action or route handler.
Iirc you can check auth in middleware and correctly remove/set cookies. **Never** check auth only inside your layout. Your page details may leak
DutchOP
how should i get the user info if client refresh the on anywhere ? forexample, client is in the dashboard page and refresh the page, how can i get the user info and store it to the redux ? then, user must continue with the same page ( where should i call getMe method ? )
@Dutch how should i get the user info if client refresh the on anywhere ? forexample, client is in the dashboard page and refresh the page, how can i get the user info and store it to the redux ? then, user must continue with the same page ( where should i call getMe method ? )
I normally check the auth in the middleware (to route correctly), check on the page as well (to get user data) and if there are any route handlers/server actions, that the client can use, I check inside them too. To secure your app, you might want to do the same
@Dutchsolved [like that](https://nextjs-forum.com/post/1433927053207539873#message-1433932953968447529)?