Repository: auth0/nextjs-auth0
Pull request #927 (2022-11-30 15:09:04)

Keep the ID Token storing default in v2
### 📋 Changes

I've decided to keep the default of storing the ID Token in the session because it may be required in RP initiated logout (we will likely require the `id_token_hint` to prevent the logout prompt by default)

### 📎 References

https://openid.net/specs/openid-connect-rpinitiated-1_0.html#:~:text=At%20the%20Logout%20Endpoint%2C%20the%20OP%20SHOULD%20ask%20the%20End%2DUser%20whether%20to%20log%20out%20of%20the%20OP%20as%20well.%20Furthermore%2C%20the%20OP%20MUST%20ask%20the%20End%2DUser%20this%20question%20if%20an%20id_token_hint%20was%20not%20provided



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 863f728d..b54aee54 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,11 +10,10 @@
 - Rearrange exports for RSC and add experimental RSC route to example [\#913](https://github.com/auth0/nextjs-auth0/pull/913) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - Improved callback errors [\#835](https://github.com/auth0/nextjs-auth0/pull/835) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - Prevent mixing named exports and own instances [\#825](https://github.com/auth0/nextjs-auth0/pull/825) ([adamjmcgrath](https://github.com/adamjmcgrath))
-- Do not store the ID token by default [\#809](https://github.com/auth0/nextjs-auth0/pull/809) ([Widcket](https://github.com/Widcket))
 - Allow to override the user prop in server-side rendered pages [\#800](https://github.com/auth0/nextjs-auth0/pull/800) ([Widcket](https://github.com/Widcket))
 - Return 204 from /api/auth/me when logged out [\#791](https://github.com/auth0/nextjs-auth0/pull/791) ([Widcket](https://github.com/Widcket))
 
-**Added**
+  **Added**
 
 - Next.js Middlware support [\#815](https://github.com/auth0/nextjs-auth0/pull/815) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - Add testing utility for generating session cookies [\#816](https://github.com/auth0/nextjs-auth0/pull/816) ([Widcket](https://github.com/Widcket))
@@ -23,6 +22,7 @@
 - Add support for configuring the default handlers [\#840](https://github.com/auth0/nextjs-auth0/pull/840) ([Widcket](https://github.com/Widcket))
 - Add logout options [\#877](https://github.com/auth0/nextjs-auth0/pull/877) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - At error cause to AT error when it's from a failed grant [\#878](https://github.com/auth0/nextjs-auth0/pull/878) ([adamjmcgrath](https://github.com/adamjmcgrath))
+- Add option to not store ID Token in session [\#809](https://github.com/auth0/nextjs-auth0/pull/809) ([Widcket](https://github.com/Widcket))
 - Default error handler [\#823](https://github.com/auth0/nextjs-auth0/pull/823) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - Allow response customization in afterCallback [\#838](https://github.com/auth0/nextjs-auth0/pull/838) ([adamjmcgrath](https://github.com/adamjmcgrath))
 - Improve API docs [\#796](https://github.com/auth0/nextjs-auth0/pull/796) ([Widcket](https://github.com/Widcket))
diff --git a/FAQ.md b/FAQ.md
index 9dac7abc..fb537f7b 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -1,6 +1,7 @@
 # Frequently Asked Questions
 
 1. [Why do I get a `state mismatch` error when logging in from different tabs?](#1-why-do-i-get-a-state-mismatch-error-if-i-try-to-log-in-from-different-tabs)
+2. [How can I reduce the cookie size?](#2-how-can-i-reduce-the-cookie-size)
 
 ## 1. Why do I get a `state mismatch` error if I try to log in from different tabs?
 
@@ -13,3 +14,14 @@ For example:
 3. Complete login on Tab 1: SDK finds Tab 2 state on the cookies and returns error.
 
 **You should handle the error and prompt the user to log in again.** As they will have an active SSO session, they will not be asked to enter their credentials again and will be redirected back to your application.
+
+## 2. How can I reduce the cookie size?
+
+The SDK stores the session data in cookies. Since browsers reject cookies larger than 4 KB, the SDK breaks up lengthier sessions into multiple cookies. However, by default Node.js limits the header size to 16 KB (Node.js version <14 has a max size of 8kb).
+
+If the session cookies are pushing the header size over the limit, **you have two options**:
+
+- Use `-max-http-header-size` to increase Node's header size.
+- Remove unused data from the session cookies.
+
+For the latter, you can add an [afterCallback](https://auth0.github.io/nextjs-auth0/modules/handlers_callback.html#aftercallback) hook to remove unused claims from the user profile. Or set the [storeIDToken](https://auth0.github.io/nextjs-auth0/interfaces/config.sessionconfig.html#storeidtoken) config to `false`, if you do not require the ID Token.
diff --git a/V2_MIGRATION_GUIDE.md b/V2_MIGRATION_GUIDE.md
index a9de3116..e308eae5 100644
--- a/V2_MIGRATION_GUIDE.md
+++ b/V2_MIGRATION_GUIDE.md
@@ -8,7 +8,6 @@ Guide to migrating from `1.x` to `2.x`
 - [`updateSession` has been added](#updatesession-has-been-added)
 - [`getServerSidePropsWrapper` has been removed](#getserversidepropswrapper-has-been-removed)
 - [Profile API route no longer returns a 401](#profile-api-route-no-longer-returns-a-401)
-- [The ID token is no longer stored by default](#the-id-token-is-no-longer-stored-by-default)
 - [Override default error handler](#override-default-error-handler)
 - [afterCallback can write to the response](#aftercallback-can-write-to-the-response)
 - [Configure default handlers](#configure-default-handlers)
@@ -201,14 +200,6 @@ export const getServerSideProps = async (ctx) => {
 
 Previously the profile API route, by default at `/api/auth/me`, would return a 401 error when the user was not authenticated. While it was technically the right status code for the situation, it showed up in the browser console as an error. This API route will now return a 204 instead. Since 204 is a successful status code, it will not produce a console error.
 
-## The ID token is no longer stored by default
-
-Previously the ID token would be stored in the session cookie, making the cookie unnecessarily large. Removing it required adding an `afterCallback` hook to the callback API route, and an `afterRefresh` hook to `getAccessToken()` –when using refresh tokens.
-
-Now the SDK will not store it by default. If you had been using hooks to strip it away, you can safely remove those.
-
-You can choose to store it by setting either the `session.storeIDToken` config property or the `AUTH0_SESSION_STORE_ID_TOKEN` environment variable to `true`.
-
 ## Override default error handler
 
 You can now set the default error handler for the auth routes in a single place.
diff --git a/src/auth0-session/config.ts b/src/auth0-session/config.ts
index 48d923ea..ec4d1c02 100644
--- a/src/auth0-session/config.ts
+++ b/src/auth0-session/config.ts
@@ -202,7 +202,7 @@ export interface SessionConfig {
   /**
    * Boolean value to store the ID token in the session. Storing it can make the session cookie too
    * large.
-   * Defaults to `false`.
+   * Defaults to `true`.
    */
   storeIDToken: boolean;
 
diff --git a/src/auth0-session/get-config.ts b/src/auth0-session/get-config.ts
index cafb21a3..cd463574 100644
--- a/src/auth0-session/get-config.ts
+++ b/src/auth0-session/get-config.ts
@@ -29,7 +29,7 @@ const paramsSchema = Joi.object({
       .optional()
       .default(7 * 24 * 60 * 60), // 7 days,
     name: Joi.string().token().optional().default('appSession'),
-    storeIDToken: Joi.boolean().optional().default(false),
+    storeIDToken: Joi.boolean().optional().default(true),
     cookie: Joi.object({
       domain: Joi.string().optional(),
       transient: Joi.boolean().optional().default(false),
diff --git a/src/config.ts b/src/config.ts
index f8d6eaea..49cfb247 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -217,7 +217,7 @@ export interface SessionConfig {
   /**
    * Boolean value to store the ID token in the session. Storing it can make the session cookie too
    * large.
-   * Defaults to `false`.
+   * Defaults to `true`.
    */
   storeIDToken: boolean;
 
diff --git a/src/session/session.ts b/src/session/session.ts
index 54f25029..11deaa33 100644
--- a/src/session/session.ts
+++ b/src/session/session.ts
@@ -68,7 +68,7 @@ export function fromTokenSet(tokenSet: TokenSet, config: Config | NextConfig): S
   });
 
   const { id_token, access_token, scope, expires_at, refresh_token, ...remainder } = tokenSet;
-  const storeIDToken = 'session' in config ? config.session.storeIDToken : false;
+  const storeIDToken = 'session' in config ? config.session.storeIDToken : true;
 
   return Object.assign(
     new Session({ ...claims }),


Test patch:
diff --git a/tests/auth0-session/config.test.ts b/tests/auth0-session/config.test.ts
index 92da3386..35786426 100644
--- a/tests/auth0-session/config.test.ts
+++ b/tests/auth0-session/config.test.ts
@@ -109,7 +109,7 @@ describe('Config', () => {
     expect(config.session).toMatchObject({
       rollingDuration: 86400,
       name: 'appSession',
-      storeIDToken: false,
+      storeIDToken: true,
       cookie: {
         sameSite: 'lax',
         httpOnly: true,
@@ -125,7 +125,7 @@ describe('Config', () => {
       session: {
         name: '__test_custom_session_name__',
         rollingDuration: 1234567890,
-        storeIDToken: true,
+        storeIDToken: false,
         cookie: {
           domain: '__test_custom_domain__',
           transient: true,
@@ -142,7 +142,7 @@ describe('Config', () => {
         rollingDuration: 1234567890,
         absoluteDuration: 604800,
         rolling: true,
-        storeIDToken: true,
+        storeIDToken: false,
         cookie: {
           domain: '__test_custom_domain__',
           transient: true,
diff --git a/tests/config.test.ts b/tests/config.test.ts
index 5654494f..e29ec1be 100644
--- a/tests/config.test.ts
+++ b/tests/config.test.ts
@@ -48,7 +48,7 @@ describe('config params', () => {
         rolling: true,
         rollingDuration: 86400,
         absoluteDuration: 604800,
-        storeIDToken: false,
+        storeIDToken: true,
         cookie: {
           domain: undefined,
           path: '/',
@@ -110,7 +110,7 @@ describe('config params', () => {
         AUTH0_COOKIE_SAME_SITE: 'lax',
         AUTH0_COOKIE_SECURE: 'ok',
         AUTH0_SESSION_ABSOLUTE_DURATION: 'no',
-        AUTH0_SESSION_STORE_ID_TOKEN: '1'
+        AUTH0_SESSION_STORE_ID_TOKEN: '0'
       }).baseConfig
     ).toMatchObject({
       auth0Logout: false,
@@ -119,7 +119,7 @@ describe('config params', () => {
       legacySameSiteCookie: false,
       session: {
         absoluteDuration: false,
-        storeIDToken: true,
+        storeIDToken: false,
         cookie: {
           httpOnly: true,
           sameSite: 'lax',
@@ -186,7 +186,7 @@ describe('config params', () => {
         },
         session: {
           absoluteDuration: 100,
-          storeIDToken: true,
+          storeIDToken: false,
           cookie: {
             transient: false
           },
@@ -206,7 +206,7 @@ describe('config params', () => {
       },
       session: {
         absoluteDuration: 100,
-        storeIDToken: true,
+        storeIDToken: false,
         cookie: {
           transient: false
         },
diff --git a/tests/handlers/callback.test.ts b/tests/handlers/callback.test.ts
index bcdac5a6..79be303d 100644
--- a/tests/handlers/callback.test.ts
+++ b/tests/handlers/callback.test.ts
@@ -202,6 +202,7 @@ describe('callback handler', () => {
       accessTokenScope: 'read:foo delete:foo',
       token_type: 'Bearer',
       refreshToken: 'GEbRxBN...edjnXbL',
+      idToken: await makeIdToken({ iss: 'https://acme.auth0.local/' }),
       user: {
         nickname: '__test_nickname__',
         sub: '__test_sub__'
@@ -240,6 +241,7 @@ describe('callback handler', () => {
     expect(session).toStrictEqual({
       accessTokenExpiresAt: 750,
       accessTokenScope: 'read:foo delete:foo',
+      idToken: await makeIdToken({ iss: 'https://acme.auth0.local/' }),
       token_type: 'Bearer',
       user: {
         nickname: '__test_nickname__',
diff --git a/tests/session/session.test.ts b/tests/session/session.test.ts
index 527c9a34..7a3764a8 100644
--- a/tests/session/session.test.ts
+++ b/tests/session/session.test.ts
@@ -30,20 +30,20 @@ describe('session', () => {
       });
     });
 
-    test('should not store the ID Token by default', async () => {
+    test('should store the ID Token by default', async () => {
       expect(
         fromTokenSet(new TokenSet({ id_token: await makeIdToken({ foo: 'bar' }) }), {
           identityClaimFilter: ['baz'],
           routes
         }).idToken
-      ).toBeUndefined();
+      ).toBeDefined();
     });
 
-    test('should store the ID Token', async () => {
+    test('should not store the ID Token', async () => {
       expect(
         fromTokenSet(new TokenSet({ id_token: await makeIdToken({ foo: 'bar' }) }), {
           session: {
-            storeIDToken: true,
+            storeIDToken: false,
             name: '',
             rolling: false,
             rollingDuration: 0,
@@ -53,7 +53,7 @@ describe('session', () => {
           identityClaimFilter: ['baz'],
           routes
         }).idToken
-      ).not.toBeUndefined();
+      ).toBeUndefined();
     });
   });