Description:
When handling authentication in a Next.js App Router setup, we face a limitation where cookies cannot be updated from Server Components, making it difficult to refresh and persist new access tokens during SSR (Server-Side Rendering).
Problem Scenario
- User loads a page at 10:00:00.
- Middleware runs at 10:00:00:
• Token expires at 10:00:30.
• Token is valid (30 seconds left).
• Middleware allows the request. - Server Component begins rendering at 10:00:05.
- Inside the Server Component, an API call is made at 10:00:35.
• The token has now expired.
• API returns 401 Unauthorized.
•
There’s no way to update cookies with the refreshed token.
Expected Behavior
If a token expires during a server-rendered request, there should be a mechanism for the Server Component (or the code running within it) to update cookies — for example, after calling a refresh token API.
Actual Behavior
In Server Components:
• We can read cookies using cookies() from next/headers .
• We cannot set or update cookies.
• Even if we trigger a Server Action or Route Handler from a Server Component, it cannot update cookies in the same request lifecycle.
Example Code
import { cookies } from ‘next/headers’;
export default async function Page() {
const cookieStore = await cookies();
// ❌ Cannot set cookie directly.
cookieStore.set(‘theme’, ‘dark’); // Throws error.
// ❌ Cannot update cookie via server action.
await updateCookieAction();
// ❌ Cannot update cookie via route handler call either.
await fetch(‘/api/update-cookie’, { method: ‘POST’ });
return ‘…’;
}
const JobPostings = async () => {
const response = await getAllJobPostings();
if (response.status_code === 401) {
// Refresh token successfully
const newAccessToken = await refreshAccessToken();
// ❌ Cannot update cookie from Server Component.
updateCookies(newAccessToken);
}
return (…);
};
Why This Is a Problem
Middleware can refresh tokens only on navigation requests — not for API calls made from Server Components during SSR.
This creates a gap where a page can fail to render because the server cannot persist the new token, even though it has successfully refreshed it in memory.
Questions / Suggestions
• Could there be a secure API or Response helper added to allow cookie updates from within a Server Component context?
• Alternatively, can Next.js provide a built-in authentication lifecycle hook that bridges Middleware and Server Components (e.g., to retry and persist refreshed tokens in cookies within the same request)?
