HttpOnly cookies and the BFF pattern
Because Server Actions run on the server, they can set httpOnly cookies directly in the response. The client never sees the token. Every subsequent request carries the cookie automatically. This is the Backend For Frontend pattern, and Next.js makes it almost effortless.
'use server';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
export async function login(formData: FormData) {
const username = formData.get('username') as string;
const password = formData.get('password') as string;
const res = await fetch('http://backend:3000/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (!res.ok) throw new Error('Invalid credentials');
const { token } = await res.json();
cookies().set('token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 60 * 60, // 1 hour
});
redirect('/');
}Login calls the real backend, extracts the token, and sets it as an httpOnly cookie.
Read the cookie options. httpOnly means JavaScript cannot read it, which defeats XSS token theft. secure in production means it only travels over HTTPS. sameSite lax blocks most CSRF attacks. maxAge matches the JWT expiration. This is the safest token storage story you can build in the browser, and it took ten lines of code.
Quiz: Quiz
Loading practice…