Skip to content

Commit a398b0a

Browse files
Merge branch 'main' into frederikprijck-patch-2
2 parents b8a7ff6 + 77a5b0c commit a398b0a

File tree

5 files changed

+91
-21
lines changed

5 files changed

+91
-21
lines changed

V4_MIGRATION_GUIDE.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,6 @@ If you'd like to customize the `user` object to include additional custom claims
235235
## Additional changes
236236

237237
- By default, v4 is edge-compatible and as such there is no longer a `@auth0/nextjs-auth0/edge` export.
238-
- Cookie chunking has been removed
239-
- If the cookie size exceeds the browser limit of 4096 bytes, a warning will be logged
240-
- To store large session data, please use a [custom data store](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#database-sessions) with a SessionStore implementation
241238
- All cookies set by the SDK default to `SameSite=Lax`
242239
- `touchSession` method was removed. The middleware enables rolling sessions by default and can be configured via the [session configuration](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#session-configuration).
243240
- `getAccessToken` can now be called in React Server Components.

src/client/providers/auth0-provider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function Auth0Provider({
1616
<SWRConfig
1717
value={{
1818
fallback: {
19-
"/auth/profile": user
19+
[process.env.NEXT_PUBLIC_PROFILE_ROUTE || "/auth/profile"]: user
2020
}
2121
}}
2222
>

src/server/chunked-cookies.test.ts

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,75 @@ describe("Chunked Cookie Utils", () => {
166166
);
167167
});
168168

169-
it("should log a warning when cookie size exceeds warning threshold", () => {
170-
const name = "warningCookie";
169+
it("should clear existing chunked cookies when setting a single cookie", () => {
170+
const name = "testCookie";
171+
const value = "small value";
171172
const options = { path: "/" } as CookieOptions;
172173

173-
// Create a value that exceeds the warning threshold (4096 bytes)
174-
const value = "a".repeat(4097);
174+
const chunk0 = "chunk0 value";
175+
const chunk1 = "chunk1 value";
176+
const chunk2 = "chunk2 value";
177+
178+
cookieStore.set(`${name}__1`, chunk1);
179+
cookieStore.set(`${name}__0`, chunk0);
180+
cookieStore.set(`${name}__2`, chunk2);
175181

176182
setChunkedCookie(name, value, options, reqCookies, resCookies);
177183

178-
expect(console.warn).toHaveBeenCalled();
184+
expect(resCookies.set).toHaveBeenCalledTimes(1);
185+
expect(resCookies.set).toHaveBeenCalledWith(name, value, options);
186+
expect(reqCookies.set).toHaveBeenCalledTimes(1);
187+
expect(reqCookies.set).toHaveBeenCalledWith(name, value);
188+
expect(reqCookies.delete).toHaveBeenCalledTimes(3);
189+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}__0`);
190+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}__1`);
191+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}__2`);
192+
});
193+
194+
it("should clear existing single cookies when setting a chunked cookie", () => {
195+
const name = "testCookie";
196+
const value = "small value";
197+
198+
cookieStore.set(`${name}`, value);
199+
200+
// Create a large string (8000 bytes)
201+
const largeValue = "a".repeat(8000);
202+
const options = { path: "/" } as CookieOptions;
203+
204+
setChunkedCookie(name, largeValue, options, reqCookies, resCookies);
205+
206+
expect(reqCookies.delete).toHaveBeenCalledTimes(1);
207+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}`);
208+
expect(resCookies.set).toHaveBeenCalledTimes(3);
209+
expect(reqCookies.set).toHaveBeenCalledTimes(3);
210+
});
211+
212+
it("should clean up unused chunks when cookie shrinks", () => {
213+
const name = "testCookie";
214+
const options = { path: "/" } as CookieOptions;
215+
216+
const chunk0 = "chunk0 value";
217+
const chunk1 = "chunk1 value";
218+
const chunk2 = "chunk2 value";
219+
const chunk3 = "chunk3 value";
220+
const chunk4 = "chunk4 value";
221+
222+
cookieStore.set(`${name}__1`, chunk1);
223+
cookieStore.set(`${name}__0`, chunk0);
224+
cookieStore.set(`${name}__2`, chunk2);
225+
cookieStore.set(`${name}__3`, chunk3);
226+
cookieStore.set(`${name}__4`, chunk4);
227+
228+
const largeValue = "a".repeat(8000);
229+
setChunkedCookie(name, largeValue, options, reqCookies, resCookies);
230+
231+
// It is called 3 times.
232+
// 2 times for the chunks
233+
// 1 time for the non chunked cookie
234+
expect(reqCookies.delete).toHaveBeenCalledTimes(3);
235+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}__3`);
236+
expect(reqCookies.delete).toHaveBeenCalledWith(`${name}__4`);
237+
expect(reqCookies.delete).toHaveBeenCalledWith(name);
179238
});
180239

181240
describe("getChunkedCookie", () => {

src/server/client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ export class Auth0Client {
260260

261261
allowInsecureRequests: options.allowInsecureRequests,
262262
httpTimeout: options.httpTimeout,
263-
enableTelemetry: options.enableTelemetry
263+
enableTelemetry: options.enableTelemetry,
264+
enableAccessTokenEndpoint: options.enableAccessTokenEndpoint,
264265
});
265266
}
266267

src/server/cookies.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ export { RequestCookies };
127127
const MAX_CHUNK_SIZE = 3500; // Slightly under 4KB
128128
const CHUNK_PREFIX = "__";
129129
const CHUNK_INDEX_REGEX = new RegExp(`${CHUNK_PREFIX}(\\d+)$`);
130-
const COOKIE_SIZE_WARNING_THRESHOLD = 4096;
131130

132131
/**
133132
* Retrieves the index of a cookie based on its name.
@@ -171,8 +170,6 @@ const getAllChunkedCookies = (
171170
* @param options - Options for setting the cookie.
172171
* @param reqCookies - The request cookies object, used to enable read-after-write in the same request for middleware.
173172
* @param resCookies - The response cookies object, used to set the cookies in the response.
174-
*
175-
* @throws {Error} If the cookie size exceeds the warning threshold.
176173
*/
177174
export function setChunkedCookie(
178175
name: string,
@@ -183,19 +180,18 @@ export function setChunkedCookie(
183180
): void {
184181
const valueBytes = new TextEncoder().encode(value).length;
185182

186-
if (valueBytes > COOKIE_SIZE_WARNING_THRESHOLD) {
187-
console.warn(
188-
`The cookie size exceeds ${COOKIE_SIZE_WARNING_THRESHOLD} bytes, which may cause issues in some browsers. ` +
189-
"Consider removing any unnecessary custom claims from the access token or the user profile. " +
190-
"Alternatively, you can use a stateful session implementation to store the session data in a data store."
191-
);
192-
}
193-
194183
// If value fits in a single cookie, set it directly
195184
if (valueBytes <= MAX_CHUNK_SIZE) {
196185
resCookies.set(name, value, options);
197186
// to enable read-after-write in the same request for middleware
198187
reqCookies.set(name, value);
188+
189+
// When we are writing a non-chunked cookie, we should remove the chunked cookies
190+
getAllChunkedCookies(reqCookies, name).forEach(cookieChunk => {
191+
resCookies.delete(cookieChunk.name);
192+
reqCookies.delete(cookieChunk.name);
193+
});
194+
199195
return;
200196
}
201197

@@ -213,6 +209,23 @@ export function setChunkedCookie(
213209
position += MAX_CHUNK_SIZE;
214210
chunkIndex++;
215211
}
212+
213+
// clear unused chunks
214+
const chunks = getAllChunkedCookies(reqCookies, name);
215+
const chunksToRemove = chunks.length - chunkIndex;
216+
217+
if (chunksToRemove > 0) {
218+
for (let i = 0; i < chunksToRemove; i++) {
219+
const chunkIndexToRemove = chunkIndex + i;
220+
const chunkName = `${name}${CHUNK_PREFIX}${chunkIndexToRemove}`;
221+
resCookies.delete(chunkName);
222+
reqCookies.delete(chunkName);
223+
}
224+
}
225+
226+
// When we have written chunked cookies, we should remove the non-chunked cookie
227+
resCookies.delete(name);
228+
reqCookies.delete(name);
216229
}
217230

218231
/**

0 commit comments

Comments
 (0)